说在前面
用自己的号打了第一场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,当节点数很多的时候,图必然是由一个巨大的联通块和很多小联通块构成,有多小呢?
size≤MN−siz
s
i
z
e
≤
M
N
−
s
i
z
。于是可以考虑数据分治。在n不超过
4000
4000
的时候,都选用
N2
N
2
算法(当然可以更大,只要不会T就可以)。而当n大于
4000
4000
的时候,只有那些断边超过
N−50
N
−
50
的节点才可能在小联通块内,于是我们也只搜索这些点。在dfs时用一个栈储存经过了哪些点,如果说栈内元素超过了50个,说明这不是一个独立联通块,于是直接return,并且把栈内元素信息复原即可。
F
每次把一个区间内的数字变成它的约数个数
一个数
n
n
的约数个数一定不会超过个,也就是说,每个数最多被操作几次,就会变得很小很小,最后要么等于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个,所以容斥复杂度是可以接受的,那么总复杂度是
Qlog2N∗27
Q
l
o
g
2
N
∗
2
7
,大概是7800k,五秒的时限是可以跑过去的