刷(shui)题记录 2021.11

[JOISC2020] 首都

⇒ \Rightarrow 原题链接

可以想到,答案实际上是选择的城市数量减去 1 1 1

选择的城市的所有城镇要连成一个联通块,那么对于属于同一个城市中的两个城镇 x , y x,y x,y ,假如选择了这个城市,那么路径 ( x , y ) (x,y) (x,y) 上所有的城镇所属于的城市都要被选择。因此可以建一个新图,对于路径 ( x , y ) (x,y) (x,y) 上的所有除 x , y x, y x,y 的点 p p p ,建边 C x → C p C_x\rightarrow C_p CxCp 。那么答案就等于新图中最小的没有出度的强连通分量的节点个数。但是这样建边的边数为 O ( n 2 ) O(n ^ 2) O(n2) 的。

首先可以想到用树链剖分+线段树优化建图优化,但是边数依然是 O ( n log ⁡ 2 2 n ) O(n \log_2^2 n) O(nlog22n) 的,会 MLE \verb|MLE| MLE

可以用类似的思路+倍增,对于原图的点 u u u 其建边方式如下:

( u , 0 ) = C f a u f o r   i > 0 ,   ( u , i ) → ( u , i − 1 ) , ( u , i ) → ( f a u , i − 1 , i − 1 ) (u,0) = C_{\mathrm{fa}_u}\\ \mathrm{for}~i > 0,~(u,i)\rightarrow (u,i-1), (u,i)\rightarrow (\mathrm{fa}_{u,i-1}, i - 1) (u,0)=Cfaufor i>0, (u,i)(u,i1),(u,i)(fau,i1,i1)

其中 ( u , i )   ( i > 0 ) (u,i)~(i>0) (u,i) (i>0) 表示新图中的一个节点。

那么对于任何一组 ( x , y ) (x,y) (x,y) ,其连边方式就很明显了。

[AGC043-B] 123 Triangle

⇒ \Rightarrow 原题链接

对于第二行开始的所有 f f f 值,都是 0 / 1 / 2 0/1/2 0/1/2 中的一个,可以首先将第一行的 f f f 都减去 1 1 1 ,让所有的 f f f 的值域相同。

考虑首先判断答案的奇偶性,可以发现奇偶性数组 g ( i , j ) = g ( i − 1 , j ) ⊕ g ( i − 1 , j + 1 ) g(i,j)=g(i-1,j)\oplus g(i-1,j+1) g(i,j)=g(i1,j)g(i1,j+1) ⊕ \oplus 表示异或)。

那么可以得到
g ( N , 1 ) ≡ ⨁ i = 1 N ( N − 1 i − 1 ) g ( 1 , i ) ( m o d 2 ) g(N,1) \equiv \bigoplus_{i=1}^N \binom{N-1}{i-1} g(1,i) \pmod{2} g(N,1)i=1N(i1N1)g(1,i)(mod2)

在模 2 2 2 的情况下,有 ( a b ) = [ a   a n d   b = b ] \binom{a}{b}=[a~\mathrm{and}~b = b] (ba)=[a and b=b]

接下来判断 g ( N , 1 ) = 0 g(N,1)=0 g(N,1)=0 情况下的答案。可以想到如果存在至少一个 1 1 1 ,那么答案必然为 0 0 0 ,因为 2 2 2 遇到 1 1 1 都会变成 1 1 1

接下来只要判断只有 0 / 2 0/2 0/2 的情况,显因为 2 − 2 = 0 , ∣ 0 − 2 ∣ = ∣ 2 − 0 ∣ = 2 2-2=0,|0-2|=|2-0|=2 22=0,02=20=2 ,这个很像 g ( i , j ) g(i,j) g(i,j) 的计算过程,设新的数组是 h h h ,那么就有:

h ( N , 1 ) ≡ ⨁ i = 1 N ( N − 1 i − 1 ) [ f ( 1 , i ) = 2 ] ( m o d 2 ) h(N,1) \equiv \bigoplus_{i=1}^N \binom{N-1}{i-1} [f(1,i)=2] \pmod{2} h(N,1)i=1N(i1N1)[f(1,i)=2](mod2)

如果 h ( N , 1 ) = 1 h(N,1)=1 h(N,1)=1,那么最终答案就是 2 2 2,否则就是 0 0 0

[ARC119-D] Grid Repainting 3

⇒ \Rightarrow 原题链接

先建个图,对于矩阵中 s i , j = R s_{i,j} = \verb|R| si,j=R 的位置,在图上建立 i ↔ j + N i \leftrightarrow j+N ij+N

矩阵上选择一个位置进行操作实际上就是对于图中一条边,选择其中一端。

考虑白块个数的计算方式,参数显然是被覆盖为白色的行数和列数,设其分别为 a , b a,b a,b ,可以得到:
A N S ( a , b ) = a M + b N − a b \mathrm{ANS}(a,b) = aM+bN - ab ANS(a,b)=aM+bNab

考虑我们在新图中的选择方案,可以发现实际上就是找到一颗 d f s \mathrm{dfs} dfs 树,由底向上“操作”,然后舍去根节点,也就是说,对于一个联通块,我们必须舍去一行或者一列。这里稍微解释一下“操作”是什么意思:对于一条在 d f s \rm dfs dfs 树上的边 x ↔ y x\leftrightarrow y xy x x x 为父亲),如果 y y y 是行节点,那么就是将 ( y , x − N ) (y, x - N) (y,xN) 所在的行覆盖为白色;如果 y y y 是列节点,那么就是将 ( x − N , y ) (x - N, y) (xN,y) 所在的列覆盖为白色。

枚举多少个联通块舍去了一行,得到最优的参数 a , b a,b a,b,然后对于每个联通块,选好根节点是行节点还是列节点,然后 d f s \rm dfs dfs 得到方案。

[LG-P4437] [HNOI/AHOI2018]排列

⇒ \Rightarrow 原题链接

对题目进行转化,对于任意一个 i i i ,建立节点 a i → i a_i \rightarrow i aii ,可以认为原问题变成了选择一个 0 ⋯ n 0 \cdots n 0n 的排列 P P P ,满足儿子节点 u u u P u P_u Pu 大于父亲节点 v v v P v P_v Pv ,而我们要令 ∑ i = 1 n p i w i \sum_{i=1}^n p_i w_i i=1npiwi 最大。这个很像某道题,但是数据规模更大,用并查集和优先队列优化一下。

[LG-P7026] [NWRRC2017]Hidden Supervisors

⇒ \Rightarrow 原题链接

首先考虑如果没有不确定祖先的的点,最终答案怎么求,显然可以按深度从大到小考虑,如果一个节点 u u u 存在儿子节点 v v v 没有被选择,那么就选择 u u u v v v 作为一对。可以发现,如果存在两种最优方案,其中一种选择了根节点,另一种没有选择根节点,那么这种算法会选择不选根节点的那种。

接着考虑原题。我们要进行的操作就是将森林中每棵树的根节点(除了节点 1 1 1)都选择一个往上的节点。首先对于每棵树都跑一遍上面提到的算法,接着分类思考一下:

T u T_u Tu 是某棵树 T T T 的根节点。

  • 当前森林中不存在 T T T 之外的没有选择的节点,那么这时候可以直接将 T u T_u Tu 连到 1 1 1
  • 当前存在 T T T 之外的没有选择的节点:
    • T u T_u Tu 已经被选择,那么这时假如改变方案,使 T u T_u Tu 选择这个在 T T T 之外的节点,那么对于 T T T 中的方案的贡献,至少会减少 1 1 1 ,一定不会更优,因此 T u T_u Tu 一样直接连到 1 1 1
    • 显然可以让 T u T_u Tu 连接到这个节点就行了,匹配数 + =   1 +=\ 1 += 1

这样就能得到算法了,首先将所有选择了 T u T_u Tu 的树都连到 1 1 1 。对于剩下的,为了尽量增加匹配数,可以按没有选择的节点个数由大到小考虑。

[LG-P6071] 『MdOI R1』Treequery

⇒ \Rightarrow 原题链接

首先用 ST \verb|ST| ST 表得到任何一个区间的 L C A \rm LCA LCA ,方便接下来的操作。

T u T_u Tu 表示以 u u u 为根节点的子树的所有节点。

接下来大力分类思考:

  • [ l , r ] ⊂ T u [l,r]\subset T_u [l,r]Tu :那么答案显然是 d i s ( p , L C A ( l , r ) ) \mathrm{dis}(p, \mathrm{LCA}(l,r)) dis(p,LCA(l,r))
  • [ l , r ] ⊄ T u [l,r] \not \subset T_u [l,r]Tu
    • [ l , r ] ∩ T u ≠ ∅ [l,r] \cap T_u \not = \empty [l,r]Tu=,那么答案显然为 0 0 0
    • [ l , r ] ∩ T u = ∅ [l,r] \cap T_u = \empty [l,r]Tu=
      • p ∉ T L C A ( l , r ) p \not\in T_{\mathrm{LCA}(l,r)} pTLCA(l,r),那么答案一样是 d i s ( p , L C A ( l , r ) ) \mathrm{dis}(p, \mathrm{LCA}(l,r)) dis(p,LCA(l,r))
      • p ∉ T L C A ( l , r ) p \not\in T_{\mathrm{LCA}(l,r)} pTLCA(l,r),这时候首先要找到深度最小的,满足没有任何一个 [ l , r ] [l,r] [l,r] 中的节点在其子树的节点 u u u ,这个东西可以用倍增跳。答案就是 d i s ( u , p ) + 1 \mathrm{dis}(u,p)+1 dis(u,p)+1

接下来只需要考虑怎么求出某棵子树 T u T_u Tu 中编号在某个区间 [ l , r ] [l,r] [l,r] 中的节点个数就行了。这相当于求出下面的问题:

Q ( u , l , r ) = ∑ i = l r [ d f n ( u ) ≤ d f n ( i ) < d f n ( u ) + ∣ T u ∣ ] Q(u,l,r) = \sum_{i=l}^r \left[\mathrm{dfn}(u)\leq \mathrm{dfn}(i) < \mathrm{dfn}(u)+|T_u|\right] Q(u,l,r)=i=lr[dfn(u)dfn(i)<dfn(u)+Tu]

这时候显然有 Q ( u , l , r ) = Q ( u , 1 , r ) − Q ( u , 1 , l − 1 ) Q(u,l,r)=Q(u,1,r)-Q(u,1,l-1) Q(u,l,r)=Q(u,1,r)Q(u,1,l1) 。然后用可持久化线段树维护 Q ( u , 1 , l i m ) Q(u,1,lim) Q(u,1,lim) 的答案就行了。

[ARC103-D] Distance Sums

⇒ \Rightarrow 原题链接

考虑一条边 ( u , v ) (u,v) (u,v) 其中 u u u v v v 的父亲,那么一定有
D u − D v = n − 2 ∣ T v ∣ → D u = D v − 2 ∣ T v ∣ + n D_u - D_v = n -2|T_v| \rightarrow D_u = D_v - 2|T_v| + n DuDv=n2TvDu=Dv2Tv+n
因为 D u D_u Du 互不相同,同时因为 D u D_u Du 最大的点一定是某一个叶子, D u D_u Du 最小的点一定是重心,因此按 D D D 由大到小考虑,直接由上面的式子求出父亲,然后 check \verb|check| check 一下根节点是否符合就行了。

[AGC007-D] Shik and Game

⇒ \Rightarrow 原题链接

根据经验,可以认为最优方案一定是将 N N N 只小熊分成若干段,从左到右考虑,对于一段小熊,操作一定是首先从左到右依次激活,然后折返回最左边的小熊,然后从左往右收取金币,然后向右离开这一段小熊,可以证明这是最优的。

f ( i ) f(i) f(i) 表示考虑了前 i i i 只小熊的最小花费,显然有:
f ( i ) = min ⁡ j = 1 i { f ( i − j ) + x i − x i − j + min ⁡ { 2 ( x i − x i − j + 1 ) , T } } f(i)=\min_{j=1}^i \{f(i-j)+x_i-x_{i-j}+\min\{2(x_i-x_{i-j+1}), T\}\} f(i)=j=1mini{f(ij)+xixij+min{2(xixij+1),T}}

这个转移是 O ( n 2 ) O(n^2) O(n2),但是有极大的优化空间,将所有 j j j 按照 2 ( x i − x i − j + 1 ) 2(x_i-x_{i-j+1}) 2(xixij+1) T T T 的大小关系分成两部分,可以发现两部分分别可以用前缀最小值和线段树之类的进行优化。

[AGC006-C] Rabbit Exercise

⇒ \Rightarrow 原题链接

首先考虑一次跳跃之后第 a a a 只兔子位置的变化,可以得到 x a ′ = 1 2 ( 2 x a + 1 − x a ) + 1 2 ( 2 x a − 1 − x a ) = x a + 1 + x a − 1 − x a x'_a=\frac{1}{2}(2x_{a+1}-x_a)+\frac{1}{2}(2x_{a-1}-x_a)=x_{a+1}+x_{a-1}-x_a xa=21(2xa+1xa)+21(2xa1xa)=xa+1+xa1xa。这个计算要进行 m k mk mk 次,很难优化。

考虑差分,设 d i = x i − x i − 1 d_i=x_i-x_{i-1} di=xixi1 ,一次操作会改变 d a d_a da d a + 1 d_{a+1} da+1 ,考虑其变化:
d a ′ = x a ′ − x a − 1 = x a + 1 − x a = d a + 1 d a + 1 ′ = x a + 1 − x a ′ = x a − x a − 1 = d a \begin{aligned} d'_a &= x'_a - x_{a-1}=x_{a+1}-x_a=d_{a+1}\\ d'_{a+1} &= x_{a+1}-x'_a =x_a-x_{a-1}=d_a \end{aligned} dada+1=xaxa1=xa+1xa=da+1=xa+1xa=xaxa1=da
可以发现这实际上是交换 d a , d a + 1 d_a, d_{a+1} da,da+1
因此可以处理出一轮操作之后每一个 d a d_a da 去了哪里,这东西建图之后一定会形成若干个环,对于每一个环都计算出操作 k k k 轮之后的 d d d 就行了。

[ARC124-D] Yet Another Sorting Problem

⇒ \Rightarrow 原题链接

依然是排列排序题,建图 i → p i i\rightarrow p_i ipi ,可以得到若干个环。环内元素的交换实际上就是将环分裂成两个。环之间元素的交换是将两个环合并成一个。

对于跨越两个部分的环,也就是存在一个位置 ≤ N \leq N N ,存在一个位置 > N >N >N 的环,将其内部排好序的操作次数显然是环大小 −   1 -\ 1  1
对于只包含左边部分和只包含右边部分的两个环 c 1 , c 2 c_1, c_2 c1,c2,可以考虑将两个环合并。

因此答案为 n + m − c + 2 max ⁡ { a , b } n+m-c+2\max\{a,b\} n+mc+2max{a,b},其中 c c c 表示环的总个数(包括自环), a , b a,b a,b 分别表示只包含左边的环的个数和只包含右边的环的个数。

[ARC126-D] Pure Straight

⇒ \Rightarrow 原题链接

看到 K K K 很小,可以考虑一下状态压缩 dp \verb|dp| dp 。在这之前先思考一下怎么拼凑出一个 ( 1 , 2 , ⋯ K ) (1,2,\cdots K) (1,2,K) 的子串。首先对于一个长度为 K K K 的排列,需要的步数显然是逆序对数,现在想想在一个排列中参杂一些不用来构成子串的元素,那么显然是要将他们全部跳过,可以是让所有在其右边的需要用的元素跳到其左边,也可以是在其左边的需要用的元素都移到右边。这些显然很适合用 dp \verb|dp| dp 来计算。

f ( i , S , 0 / 1 ) f(i,S,0/1) f(i,S,0/1) 表示当前考虑了前 i i i 个元素,已经拼凑出了一个 S S S 中的所有元素排好序的子串,这个子串的位置是否被固定,如果没有被固定,要求这个子串的末尾在 i i i 。考虑转移,显然对于一个新的元素,可以选择不使用,也可以选择加入 S S S

  • 如果不使用这个元素,那么如果子串位置被固定,所有在这个元素右边的,没有加入 S S S 的元素都必须向左跳过这个字符,而跳过这个元素需要 ∣ ∁ U S ∣ |\complement_U S| US 步;如果没有被固定,那么这个子串需要跳过这个字符,这需要 ∣ S ∣ |S| S 步,接下来可以选择是否在这个位置固定子串。
  • 如果使用这个元素,假设其是 X X X,如果子串位置不固定,这个字符首先要跳到子串中恰当的位置,这需要 ∑ y ∈ S [ y > X ] \sum_{y\in S}[y>X] yS[y>X] 步,相当于求个逆序对数;如果子串位置被固定了,但是先前已经计算了这个元素跳过无用元素所需要的操作数,所以既然是相同的步数。

[ARC125-D] Unique Subsequence

⇒ \Rightarrow 原题链接

f ( i ) f(i) f(i) 表示结尾为第 i i i 个元素的独一无二子序列的个数,那么可以得到转移:
f ( i ) = ∑ j < i f ( j ) × [ ∀ j < k < i , a k ≠ a j , a k ≠ a i ] f(i)=\sum_{j<i}f(j)\times[\forall j<k<i,a_k\ne a_j, a_k\ne a_i] f(i)=j<if(j)×[j<k<i,ak=aj,ak=ai]
这个显然可以用线段树或者一个桶优化。

[ARC130-D] Zigzag Tree

⇒ \Rightarrow 原题链接

可以想到树形 dp \verb|dp| dp ,具体而言:

f ( u , x ) , g ( u , x ) f(u,x), g(u,x) f(u,x),g(u,x) 分别表示子树 T u T_u Tu 中,节点 u u u 的值为子树中第 x x x 小的,设定 u u u 的父亲要比 u u u 小/大的方案数。转移方式考虑树形背包式的合并子树。考虑将 g ( v , ? ) g(v,?) g(v,?) 合并到 f ( u , ? ) f(u,?) f(u,?) 中。显然这时候需要另 v v v 的值比 u u u 的值小,同时需要枚举 T v T_v Tv 中多少个值比 u u u 的值要小,这时可以得到 O ( n ) O(n) O(n) 的刷表转移:

f o r e a c h    z ∈ [ y , ∣ T v ∣ ] ∩ Z , f ′ ( u , x + z ) ← ( x + z − 1 x − 1 ) ( ∣ T u ∣ + ∣ T v ∣ − x − z ∣ T u ∣ − x ) f ( u , x ) g ( v , y ) \mathrm{foreach}~~z\in [y,|T_v|]\cap \mathbb{Z}, f'(u,x+z)\leftarrow \binom{x+z-1}{x-1}\binom{|T_u|+|T_v|-x-z}{|T_u|-x}f(u,x)g(v,y) foreach  z[y,Tv]Z,f(u,x+z)(x1x+z1)(TuxTu+Tvxz)f(u,x)g(v,y)

这个可以直接使用前缀和优化,做到 O ( 1 ) O(1) O(1) 刷表转移。

同理,要将 f ( v , ? ) f(v,?) f(v,?) 合并到 g ( u , ? ) g(u,?) g(u,?) 中,可以使用下面的方式:

f o r e a c h    z ∈ [ y , ∣ T v ∣ ] ∩ Z , f ′ ( u , x + z − 1 ) ← ( x + z − 2 x − 1 ) ( ∣ T u ∣ + ∣ T v ∣ − x − z + 1 ∣ T u ∣ − x ) g ( u , x ) f ( v , y ) \mathrm{foreach}~~z\in [y,|T_v|]\cap \mathbb{Z}, f'(u,x+z-1)\leftarrow \binom{x+z-2}{x-1}\binom{|T_u|+|T_v|-x-z+1}{|T_u|-x}g(u,x)f(v,y) foreach  z[y,Tv]Z,f(u,x+z1)(x1x+z2)(TuxTu+Tvxz+1)g(u,x)f(v,y)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值