前言
T1: CF1213G
T2: CF1343D
T3: CF1360H(加强版)
T4: CF1370D
T5: CF1363E
T6: P6833(Luogu September Contest T2)
T7: CF1328E
T8: CF1209D
T9: ABC146E
T10: P5664(CSP-S 2020 D2T1)
T11: 不知道
T12: P4281(AHOI2008)
T13: P2491(SDOI2011)
T14: P1989
T15: CF804D
T16: LOJ #10222
T17: P6569(NOI Online #3 提高组)
T18: P4159(SCOI2009)
T19: P2051(AHOI2009)
T20: CF516D
T21: CF1404B
T22: NOIP 2020模拟赛D1T3
T23: P3401
Solution
T1
假设我们已得到了 k k k的答案,那 k + 1 k+1 k+1的答案是什么呢?我们可以加入所有权值为 k + 1 k+1 k+1的边,然后答案就是 ∑ C s i z e , 2 \sum C_{size,2} ∑Csize,2,其中 s i z e size size表示一个联通块的大小。于是,我们预处理出 k = 1 , 2 , 3 … … , m a x w k=1,2,3……,maxw k=1,2,3……,maxw的答案,询问时直接 O ( 1 ) O(1) O(1)调用即可。
此时,我们可以使用并查集来维护。即,我们将两个大小为 x , y x,y x,y的集合合并后,对答案的贡献从 C x 2 + C y 2 C_{x}^2+C_{y}^2 Cx2+Cy2变成了 C x + y 2 C_{x+y}^2 Cx+y2,所以我们可以实时维护这个答案。
使用按秩合并的并查集可以将时间复杂度优化到 O ( n + q ) O(n+q) O(n+q)。
T2
可以发现,对于每一对相对应的值 x , y x,y x,y,可以通过 0 0 0次操作变成 x + y x+y x+y,通过 1 1 1次操作变成 [ 1 + y , k + y ] [1+y,k+y] [1+y,k+y]和 [ x + 1 , x + k ] [x+1,x+k] [x+1,x+k]的并集与{ x + y x+y x+y}的差集,通过 2 2 2次操作变成其他的数。
所以,我们分别枚举两个对应位置的数,然后按照上述方式进行若干次区间修改,在一个桶中记录,其中这个桶的第 i i i位表示当所有对应位置和为 i i i时的最少操作次数。最终查询桶中所有数的最小值即可。
通过差分可以将时间复杂度优化到 O ( n ) O(n) O(n)。
T3
考虑二分。
假设二分的值为 x x x,那么如何快速求出 x x x在未被删除的数中的排名呢?这个显然也可以二分。
如果排名低了,就向上;否则向下。
于是总时间复杂度为 O ( l o g ( 2 m ) l o g n ) = O ( m l o g n ) O(log(2^m)logn)=O(mlogn) O(log(2m)logn)=O(mlogn)
看到时限0.1s是不是觉得我很毒瘤
T4
考虑二分。
假设二分的值为 m i d mid mid,那么我们就将这个序列转化为了一个 01 01 01序列,所有大于 m i d mid mid的数为 1 1 1,其他数为 0 0 0。现在,如果满足最小的代价不大于 m i d mid mid,那么我们就要选出这个 01 01 01序列中偶数位均为 0 0 0或奇数位均为 0 0 0的最长子序列之长度。
我们分别枚举"奇数位均为 0 0 0"与"偶数位均为 0 0 0",可以在 O ( n ) O(n) O(n)的时间复杂度内判断。如果可以,说明可以尝试让代价更小;否则只能让代价更大。
时间复杂度 O ( n l o g m ) O(nlogm) O(nlogm),其中 m m m为序列中的最大值。
T5
显然,如果一个节点已经被对上了号(即它的当前点权等于它的目标点权),在最优决策中,任何一次操作都不可能与它有关。此时,现在的节点分为两类: 0 0 0要变成 1 1 1的, 1 1 1要变成 0 0 0的。定义在节点 x x x的子树中,属于第一类的有 a x a_x ax个节点,属于第二类的有 b x b_x bx个节点。
显然,一个节点能够做的所有操作,它的祖先都能完成。换句话说,当且仅当这个节点的操作代价比它任何祖先的操作代价都要小,我们才需在该节点的子树中进行操作,其代价为该节点的代价乘上操作的次数。
对于一个节点的子树中,可以进行 m i n ( a x , b x ) × 2 min(a_x,b_x)×2 min(ax,bx)×2次有意义的操作,代价为 m i n ( a x , b x ) × 2 × w x min(a_x,b_x)×2×w_x min(ax,bx)×2×wx。此时, a x a_x ax与 b x b_x bx中 a x a_x ax归 0 0 0(不妨设 a x a_x ax是较小的), b x b_x bx就会减去 a x a_x ax。我们实时递推得到每个节点的 a x a_x ax与 b x b_x bx即可。递推式显然, a x = ∑ a s o n a_x=\sum a_{son} ax=∑ason, b x b_x bx同理。
综上所述,我们通过比较显然的贪心,在 O ( n ) O(n) O(n)的时间复杂度内解决了本题。
T6
考虑图论建模。
我们枚举 x − > y x->y x−>y, x − > z x->z x−>z的交点 a a a,那么路径并集的权值之和就是 x − > a x->a x−>a, a − > y a->y a−>y, a − > z a->z a−>z,每次只需要调用 x , y , z x,y,z x,y,z到 a a a的最短路径。
于是,我们在建图之后跑 3 3 3遍单源最短路径即可,此时对于每个 a a a均可以 O ( 1 ) O(1) O(1)查询。
时间复杂度 O ( n m log ( n m ) ) O(nm \log{(nm)}) O(nmlog(nm))。
T7
显然,只需要到达一个节点的父亲节点就可以了,不需要再向下走了。
所以,我们预处理出每个节点的父亲节点,在询问中,判断询问的节点的父节点是否构成了一条以根节点为一端的一条链。判断方法套路,我们将每个节点按照深度排序,如果存在一个节点使它的任何祖先都不是上一个节点,那么就不满足要求;否则一定满足要求。
至于判断一个节点是否是另一个节点的祖先,可以通过预处理+倍增来完成,就是将偏下的节点跳到另一个节点同高度的位置,再判断它们是否为同一个节点即可。
时间复杂度 O ( ( n + k ) l o g n ) O((n+k)logn) O((n+k)logn)。
T8
考虑图论建模。对于每对花的编号 u , v u,v u,v,从 u u u 到 v v v 连一条无向边。
接着,对整个不一定联通的图做 b f s bfs bfs。对于每个节点,如果它没有被访问过,那么我们就 b f s bfs bfs 下去,每次扩展一层,即扩展出当前队列开头的节点的各个连点。
于是,最多的开心客人的数量就是在 b f s bfs bfs 过程中经过的边的数量。注意答案询问的是悲伤的客人的最小值,所以还要用 k k k来减去它。
时间复杂度 O ( n ) O(n) O(n)。
T9
特注: 由于懒的原因,本蒟蒻把所有的 b 6 e 0 b6e0 b6e0换成了 k k k,方便书写
先推一波式子:
( ∑ i = l r a i ) m o d k = r − l + 1 (\sum_{i=l}^r a_i)\ mod\ k=r-l+1 (∑i=lrai) mod k=r−l+1
假设 r − l + 1 < k r-l+1<k r−l+1<k,那么
( ∑ i = l r a i ) − ( ∑ i = l r 1 ) ) m o d k = 0 (\sum_{i=l}^r a_i)-(\sum_{i=l}^r 1))\ mod\ k=0 (∑i=lrai)−(∑i=lr1)) mod k=0
( ∑ i = l r ( a i − 1 ) ) m o d k = 0 (\sum_{i=l}^r (a_i-1))\ mod\ k=0 (∑i=lr(ai−1)) mod k=0
我们先把序列中的所有数减 1 1 1。此时相当于,我们要求多少个长度小于 k k k的区间,使得该区间的和膜 k k k的值为 0 0 0。
采用前缀和的思想,一个区间 [ l , r ] [l,r] [l,r]满足上述要求,显然需要 p r e r pre_r prer与 p r e l − 1 pre_{l-1} prel−1两个值在膜 k k k的意义下同余。所以,我们开桶( m a p map map),记录当前这种余数在前缀和数组 p r e pre pre中出现的次数。我们枚举 r r r,查表中与 p r e r pre_r prer同余的数的数量即可,同时维护这个桶的方式也并不难,每次我们的 r r r变成 r + 1 r+1 r+1的时候,把 p r e r − k pre_{r-k} prer−k的贡献去除即可。
时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)。
T10
正面思考十分复杂,考虑反面思考。
首先,我们假定,所有情况都要求每一行均最多取 1 1 1个。那么,此时不满足要求的情况当且仅当存在某列被取了超过一半次——即,该列被取的次数减去别的列被取的次数为正数。
定义第 x x x列不满足要求当且仅当第 x x x列被取的次数超过了 ⌊ k 2 ⌋ \lfloor \frac k 2 \rfloor ⌊2k⌋,显然最多只会有一列不满足。于是,我们枚举到了 n o w now now这一列不满足。
考虑 d p dp dp。
状态设计: d p i , n u m dp_{i,num} dpi,num表示看到了第 i i i行, n u m num num为目前选第 n o w now now列的次数减去选别的列的次数。
状态转移显然:对于每一行,我们只有三种取法:
①不取。此时 d p i , n u m = d p i − 1 , n u m dp_{i,num}=dp_{i-1,num} dpi,num=dpi−1,num
②取第 n o w now now列。此时 d p i , n u m = d p i − 1 , n u m − 1 × a i , n o w dp_{i,num}=dp_{i-1,num-1}×a_{i,now} dpi,num=dpi−1,num−1×ai,now
③取不是 n o w now now的列。此时 d p i , n u m = d p i − 1 , n u m + 1 × ( t o t i − a i , n o w ) dp_{i,num}=dp_{i-1,num+1}×(tot_i-a_{i,now}) dpi,num=dpi−1,num+1×(toti−ai,now),其中 t o t i tot_i toti表示第 i i i行所有数的和。
综上所述,我们枚举不满足要求的列,然后每次在 O ( n 2 ) O(n^2) O(n2)的代价下用二维 d p dp dp求出该情况的答案。时间复杂度 O ( n 2 m ) O(n^2m) O(n2m)。
T11
看到行数只有 2 2 2,大家应该很敏感了吧。
考虑状压 d p dp dp。状态设计显然: d p i , j , s t a t e dp_{i,j,state} dpi,j,state表示看了前 i i i列,这一列方格填的方案为 s t a t e state state,总共有 j j j个联通块的涂色方案数。
状态转移显然,请读者自己思考。