[Edu. Cf. Round 37]深夜肝比赛

说在前面

用自己的号打了第一场CF
两个小时的场子,时间本来就有点点少,自己洗漱还耽误了一些时间…
导致后面的题只能嘴巴AC

UPD:发现me的E题居然被hack了…me感觉me的第一场比赛已经凉凉了


关于比赛

比赛传送门
这次比赛题挺简单的,不知道是不是因为叫做「educational」的缘故
不少人都AK了,题目也比较套路,略微依赖模型和结论

解法

A

很简单,只需要判断一下相邻两个水龙头的距离的最大值(有一点细节),算出答案,然后与 起始 和 末尾 的距离取个max即可

B

简单队列模拟
用两个vector分别存一下每个时间点入队和出队的人
然后for时间,把当前时间的人按顺序入队,然后取出队首更新答案。对于需要在当前时间出队的,用一个leave数组打标记即可(出对的时候如果leave为true,则跳过此人)。

C

需要判断一个数字是否能挪回他应该在的位置。如果所有的a[i]到i这一段全是1就可以,不然就不行。用并查集或者随便搞搞就可以了。

D

D题me还没看,太晚了准备睡觉了

E

给出了反图,求正图的联通块。
对于每个点,用个set记录下它和哪些点不相邻
我们可以不存边然后直接dfs,使用并查集维护联通块大小。但是由于不知道该点与谁没有边,因此需要把1~N全都枚举一遍,复杂度就是 Θ(n2) Θ ( n 2 ) 的,显然需要优化
方法1:使用一个set存下所有还没有遍历到的点,在u点选择下一个到达的点时,就直接在set里选一个点v出来(当然要u,v没边),并且把v从set里erase出去,累计size即可。这样保证了每个点最多只会被遍历到一次,复杂度降为 Θ(nlog2n) Θ ( n l o g 2 n ) (set自带一个log)
方法2:注意到m不超过200000,当节点数很多的时候,图必然是由一个巨大的联通块和很多小联通块构成,有多小呢? sizeMNsiz s i z e ≤ M N − s i z 。于是可以考虑数据分治。在n不超过 4000 4000 的时候,都选用 N2 N 2 算法(当然可以更大,只要不会T就可以)。而当n大于 4000 4000 的时候,只有那些断边超过 N50 N − 50 的节点才可能在小联通块内,于是我们也只搜索这些点。在dfs时用一个栈储存经过了哪些点,如果说栈内元素超过了50个,说明这不是一个独立联通块,于是直接return,并且把栈内元素信息复原即可。

F

每次把一个区间内的数字变成它的约数个数
一个数 n n 的约数个数一定不会超过log2n个,也就是说,每个数最多被操作几次,就会变得很小很小,最后要么等于1,要么等于2。
于是直接线段树暴力修改即可。注意当一个区间里全是1或者2时就不再修改了。

G

求比x大的且与p互质的数中,第k大的那个,多组询问。
这里有一个性质,如果 gcd(i,p)=1 g c d ( i , p ) = 1 ,那么 gcd(i+p,p)=1 g c d ( i + p , p ) = 1
于是就是一个循环节,线性筛预处理欧拉函数,询问的时候大块跳phi,零散的部分使用二分+容斥,由于一百万内,不同素因子个数最多只会有7个,所以容斥复杂度是可以接受的,那么总复杂度是 Qlog2N27 Q l o g 2 N ∗ 2 7 ,大概是7800k,五秒的时限是可以跑过去的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值