课件(Part 1, PJ)

文章目录

前言

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=rl+1

假设 r − l + 1 < k r-l+1<k rl+1k,那么

( ∑ 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(ai1)) 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} prel1两个值在膜 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} prerk的贡献去除即可。

时间复杂度 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=dpi1,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=dpi1,num1×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=dpi1,num+1×(totiai,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个联通块的涂色方案数。

状态转移显然,请读者自己思考。

猜你喜欢

转载自blog.csdn.net/Cherrt/article/details/108684038