CF刷题记录

图论(3):
1、1601B,这道题用bfs可以解决,这道题前后看了很多次都不是很明白,硬看别人代码补的,因为是bfs,所以时间复杂度可以保证点的更新次数不会太大。
2、1594D,这里用扩展域并查集可以解决,扩展域并查集即在n+1~2n存第二级关系,2n+1~3n存第三级关系,以此类推。
3、1553E,首先我们将pi的值变为从0~n-1的值,然后我们考虑一个k,当我们进行循环移动操作时,i位置上的值应为(i-k)%n,那么我们就知道对于一个给定的k原先的数列是怎样的了,如果知道一个确切的k的值,我们怎么判断数组能否在最多m次操作下变成原先的数列呢,也就是问对于一个数列,我们能将任意两个数交换,将数列变成所求数列的最少操作次数,可以发现对于p[i]不等于a[i]的所有数一定会存在一些环,而我们的操作每次只能将环的大小减1,因此最小的操作次数为所有的环的大小减1,其实也相当于我们将他们看作一个一个的连通块,最小次数即n-c,c即连通块数量,那么这样的话我们只需要dfs一下或其他方式求一下连通块数量即可,但是我们枚举k是O(n)的,求连通块数量也是O(n)的,那么我们重新回到题目,我们最多操作m次,那么我们最多使2m个位置的数改变,所以我们至少有n-2m个位置应是正确的,而对于p[i]的值,每一个i都只对应一个k转移后的可能,所以当我们对每个i对应的k计数,只有当k的数量大于n-2m时我们才需要取判断这个k是否符合,但是这个k的数量也可能会有很多个呀,但其实是不会有很多个的,题目有一个奇怪的限制m<=n/3,并且所有cnt[k]的和为n,我们将所有满足cnt[k]>=n-2m的相加,即x*(n-2m)<=x*cnt[k]<=n,x<=n/(n-2m),所以x的最大值为3,因此满足的k的数量最多只有3个,因此我们对满足的k进行判断连通块数量即可。这里其实还有个问题,我们怎么去处理出连通块数量,我的做法是将a[i]与p[i]连边,进行联通块的遍历即可,a[i]就是k移动下原先数列i位置上应为的值,其实也就是(i-k)%n。
4、1552B,可以发现对任意两个选手进行判断谁强谁弱,一定存在一个人强于另一个人,也就是说胜负数一定存在一个人的数量大于等于3,所以如果存在最强者,那么最强者的数量一定为1,所以我们遍历i,不断更新最强者的信息,那么如果答案存在最强者的话,我们最后确定的最强者就是答案的最强者,那如果没有最强者呢?当我们存在3个人的胜负情况形成一个环的话,就是没有最强者的情况,因此我们再对求出的最强者去和每一个人进行比较,如果最强者仍是他的话,那么显然按照题目定义他即是最强者,否则输出-1。
5、1547G,这是一场div3的一题,有向图求路径数,显然我们考虑拓扑排序,但是我们拓扑排序其实只能处理源点开始往后能到达的点的路径信息,如果源点或其他点的前面有点指向并且我们拓扑排序中无法将这些点放入队列更新的话,我们就没法处理出正确的路径数量,其实这些点我们是可以得到是哪些点的,我们从起点开始进行dfs得出源点开始能到达的点并使他们vis[i]=true,那么没有访问到的点就是那些点,我们可以对这些点都放入拓扑排序的队列中进行更新,使他们dp[i]=0,当队列取出的点为1时,我们再让dp[1]=1,进而更新点,那么在更新点入队列时其实我们无需让vis[i]=false的点进入,因为我们已经将这样的点在一开始都放入队列中了,所以我们只需将vis[i]=true的点入队列,这样的话,当队列中的元素处理完,那么那些vis[i]=true并且入边仍不为0的点则为有无限条路径到达的点,使其dp值为-1即可。
6、1530D,给定一个排列a,保证ai!=i,求一个排列b,使a[i]=b[i]的数量尽可能多,并且每个bi!=i,我们用set存下1到n所以数,从前往后处理ai,如果当前s中有ai这个值,那么我们使bi=ai,并从s中去除ai,并且记录r[a[i]]=i,然后我们处理剩下的没匹配的位置,这些位置我们只需要将他们的bi值不等于i即可,那怎么处理呢?我们取s中的数填进去,如果当前bi=i,那么我们取s中的下一个,可以发现,这样处理完后bi=i的位置最多只有一个,而对于这个位置i来说,a[i]一定被放在了前面的一个位置,如果我们将前面放ai的位置放此时的bi,此时的位置i放ai的话,一定满足所有bi!=i,并且原先ai=bi的位置数量不变,因此这样得到的ai=bi的位置数最多,并且构造出了一组可行的b数组。
7、1511D,对第一个样例观察可以发现,我们的串一定是这样的一个形式,a, ab, ac, ad, b, bc, ... 也就是说我们一定对从a到x,不断的取ab,ac,...到最后,为什么这样是对的呢,我们取a的时候,a后面字母从a到x都取过一遍,两个是不重复的所以不会计入cost中,而对于a后面的那个字母b,c,d,...,他们后面只有a,而我们后面取b开头时又是从bb开始所以也不会重复,因此这样计入cost的数量最小,但是当n很大时,仍会出现记录cost的地方,那些地方是否需要不一样的安排呢?实际上我们这样构造出的串使得我们在一定长度内计入cost的数量最小,也就是说将其看作单位长度的价值的话,他是最小的,所以我们n很大时取str[i]=str[(i-1)%len+1],即重复前面的形式的话,得到的价值是最小的。
8、1516D,对于一个段来说只有其中的数两两互质时,其乘积才为所有数的lcm,那么我们其实能够处理出每个i往右最远能到达的点,用双指针可以实现,因为对于一个区间来说,如果符合条件,那么他的子区间也一定符合条件,对于任意给定的区间,我们可以用st表处理出f[i][j]即i位置上跳跃2的j次方后到达的点的位置,这里我对st的理解一直局限于处理i位置开始的2的j次方长度的信息,忘了st表可以处理跳跃次数,在排列里的跳跃也是用这个处理的,我们取log(n)到0判断如果跳跃后位置<=r则跳,那么cnt+=(1<<i),最后再跳一次就是r上了,这里还存在处理st表时的边界问题,我们可以取f[n+1][j],对任意j都为n+1,这样处理边界。
9、1513D,贪心,我们将a[i]和i作为一个二元组从大到小排列,那么我们从小到大考虑能不能用a[i]的花费向左向右扩展去连边,如果当前点已经被连过或与a[i]的gcd不等于a[i]时,我们就退出a[i]的连边操作,当a[i]>=p时我们退出所有操作,然后对没被连的点用p的花费去连边。
10、1506F,这是一场div3的一题,可以发现当r+c的值为偶数时,我们下一步会到和为奇数的位置,当和为奇数时,我们下一步也会到奇数的位置,我们逐步计算i到i+1所需花费的值,而对于i到i+1的话,我们存在和为奇->偶,奇->奇,偶->偶,偶->奇,并且存在值dr和dc,即r的差值和c的差值,因为题目规定一定存在解,所以一定满足dr>=dc,那么贪心来讲,当i和为奇数时,我们可以先取不花费的r+1,c+1的变换,直到dc=0,然后我们再去消除dr,可以发现消除dr的花费为(dr+1)/2,即dr除2上取整,而对于i位置和为偶数时,如果为偶->偶,存在dr=dc,此时我们必须花费dr的操作数才能到达,如果不存在的话,我们总能让r+1,c+0,去到一个和为奇数的位置,这是不会改变我们最少操作数的,因为dr>dc,所以总有一个地方需要往左下走,代替到i这个位置不会改变答案,偶->奇也是这样,所以我们就使偶数开始变为了奇数开始,也就能用前面的考虑解决了。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wlzsgl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值