当前位置: 首页 > news >正文

CF1967D Long Way to be Non-decreasing

前置知识

基环树,二分

思路

  1. 首先可以想到,选择集合次数应该被修改次数最多的点决定,所以题目实际要求是使最大操作次数最小。

  2. 经典二分模型,问题变为在每个点不超过 \(mid\) 的次修改后是否可以变为单调不降的序列。对于这个问题,考虑贪心,每个点都尽量选比前一个数大的最小值。先图论建模,对于每个值域 \(i\)\(i->b_i\) ,我们发现形成一个内向基环树森林(每个点出度为 \(1\) ),然后判定问题,相当于要求每个点在这些树上走,走不超过 \(mid\) 次,能到达的比前一个数大的最小值。

  3. 如果快速解决上面的问题,我们发现 \(a_i\) 单调不增,所以我们可以考虑用一个 指针扫值域 。每次只用快速判断任意两点在基环树上的距离(这是好做的)。我们可以考虑,将环上任意一边 \((u,b_u)\) 切掉,然后看成一颗以 \(u\) 为根的树。对于两点 \((x,y)\),如果在同一颗树且有祖先关系就直接 \(dep[x]-dep[y]\)(处理了环到环,树到树) ,如果要跨过断掉的边(即路径是 \(x->u->b_u->y\) ,其实就是从树到环的路径) 就是 \(dep[x]-dep[u]+1+dep[y]-dep[b_u]\)

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10,inf=1e9+7;
int n,m,a[N],b[N],fa[N],dfn[N],js[N],siz[N],dep[N],del[N],tot;
vector<int> ve[N];
void add(int x,int y){ve[x].push_back(y);} 
int find(int x)
{if(fa[x]==x)return x;else return fa[x]=find(fa[x]);
}
bool merge(int x,int y)
{int f1=find(x),f2=find(y);fa[f1]=f2;//要把父亲留在环上那个节点       if(f1==f2)return 0;return 1;
}
void dfs(int u)
{dfn[u]=++tot;for(int v:ve[u]){dep[v]=dep[u]+1;dfs(v);}js[u]=tot;
}
bool sub(int x,int y)
{return dfn[x]>=dfn[y]&&dfn[x]<=js[y];
} 
int jl(int x,int y)
{int f1=find(x),f2=find(y);if(f1!=f2) return inf;if(sub(x,y))return dep[x]-dep[y];if(sub(b[del[f1]],y))return dep[x]+1+dep[b[del[f1]]]-dep[y];return inf;
}
bool check(int mid)
{int cur=1;for(int i=1;i<=n;i++){while(jl(a[i],cur)>mid&&cur<=m)cur++;if(cur>m)return 0;}return 1;
}
void solve()
{cin>>n>>m;tot=0;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=m;i++)fa[i]=i,ve[i].clear(),del[i]=dep[i]=0;for(int i=1;i<=m;i++){cin>>b[i]; if(merge(i,b[i]))add(b[i],i);//建反向边 else del[find(i)]=i; }for(int i=1;i<=m;i++){if(fa[i]==i)dfs(del[i]);}int l=0,r=m,ans=-1; //注意n,m不要乱用while(l<=r){int mid=(l+r)>>1;if(check(mid))ans=mid,r=mid-1;else l=mid+1; }cout<<ans<<'\n';return ;	
} 
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--)solve();return 0;
} 
http://www.agseo.cn/news/413/

相关文章:

  • 软工第一次作业
  • 202310_FSCTF_DoYouKnowGCD?
  • WC2024 水镜 bakas trick 记录
  • 吸吸
  • 你的中间件一团糟-是时候修复它了-️
  • 超越-env-一份成熟的应用程序配置指南
  • 202404_QQ_维纳攻击
  • Typora
  • Proximal SFT:用PPO强化学习机制优化SFT,让大模型训练更稳定
  • ARC205_B Triangle Toggle题解
  • perf中 的dwarf是什么?
  • 读书笔记:一文搞懂Oracle全局临时表的统计信息管理
  • Anthropic 封禁中国资本背景企业使用Claude!国内AI编程选择将何去何从?
  • 故障处理:dul直接抽取exp文件
  • 解题报告-洛谷P3773 [CTSC2017] 吉夫特
  • ARC137E
  • 政治笔记
  • 并发编程中的乐观锁与悲观锁
  • 软件工程第一次作业(aili)
  • 软考高级“系统架构设计师”论文——论微服务架构及其应用
  • 2025-09-08 uniapp小程序赋值生效了但是页面却没变化?==》使用v-if+变量来控制元素的重新渲染
  • 真题补题笔记
  • 12.8 类与对象的绑定方法和非绑定方法
  • Graspnet视觉抓取(一)——环境搭建
  • 3. 堆排序
  • 12.7 类的property/setter/delter特性
  • 9.8
  • 总结
  • 82python解析器反查当前安装了那些依赖包
  • 【Azure Container App】查看当前 Container App Environment 中的 CPU 使用情况的API