2月做题记录

2月做题记录

✩ trick
✯ 会大部分,要\(tj\)提示
✬ 会小部分/完全没想到,看了\(tj\)才会
◈ 脑电波
✡ 有某一算法的神秘通用性质
⊗ 待补

【PR #14】安顿 ✩✯

我组合数化式子咋恁烂呢

\(k=2^K\)

区间异或和可以用前缀异或和差分一下表示,且显然前缀异或和数组一一对应了一组\(A\),所以直接考虑前缀异或和数组

相当于要求选出一个极长子序列,满足相邻俩元素的异或和不为\(X\),且\(0\)\(n\)必选

这个条件是比较严苛的,对于所有\(v\in[0,k)\)考虑把\(v\)\(v\ xor\ X\)标为同种颜色,那么对于所有同色的极长连通段,设里面两种值分别有\(a\)\(b\)个,则它的贡献就是\(\max(a,b)\)

\(X=0\)是一种情况,\(X\neq0\)是另一种情况,且\(X\neq 0\)显然等价

对于一个长为\(len\)的极长同色连续段,其概率为\((\frac{k-2}k)^2(\frac2k)^{len-1}\),总贡献是\(\sum_{i=0}^{len}C_{len}^i\max(i,len-i)\),在\(i\leq\lfloor\frac{len}2\rfloor\)时和后半对称,所以只考虑一半

需要快速计算\(\sum_{i=0}^{\lfloor\frac{len-1}2\rfloor}iC_{len}^i\),化一下式子得到\(len\sum_{i=0}^{\lfloor\frac{len-1}2\rfloor-1}C_{len-1}^{i}\)

\(f(n,m)=\sum_{i=0}^mC_n^i\),则递推式有\(f(n,m)=2f(n-1,m)-C_{n-1}^m\),然后差不多就是可以直接推

当然对于这个段在两端的情况就概率那去掉一个\(\frac{k-2}k\),然后还有整个序列都是同一个段的情况,单独搞下就好

复杂度\(O(N)\)

【PR #14】狼抓兔子

最开始想的是显然狼的匹配肯定不会出现,\(i<j\),但\(match_i>match_j\)的情况,所以可以来个\(O(N^2)\)\(dp\)

然后正解是维护\(dp[i][j]\),表示\(1\sim i\)位置,现在有\(j\)只兔子要往后匹配,若\(j\)是负的代表狼

  • 每走一步,要\(+b_{i+1}\times|j|\)
  • 如果当前是狼,若有\(a\)只,显然\(dp[i+1][j]=dp[i][j-a]\)
  • 若是兔子,有\(a\)只,不必全部放下去,则有\(dp[i+1][j]=\min_{k\in[j-a,j]}dp[i][k]\)

显然每一步都满足凸包性质,只需要支持加上一个\(V\)字形函数,整体左移,部分右移即可

可以平衡树维护的

好像有反悔贪心的做法。。。?

【PR #14】字符串 ✡✩✬

首先有个显然的在\(trie\)树上\(dp\),列出式子然后可以高消,复杂度\(O(NM^3)\)

然后可以考虑用一些主元来表示所有的元素

注意到\(n\)很小,可以考虑重链剖分,把每个重链头当作主元,显然只有\(O(N)\)

???这怎么想到的啊

考虑怎么用主元表示所有\(dp\)表示\(dp\)式,注意到转移式\(dp_x=1+\sum_{c}p_cdp_{ch[x][c]}\),注意到\(ch[x][c]\)只能指向\(x\)的儿子和\(dep\leq dep_x\)的点,它们的表达式都已经得出了,又因为\(x\)只有一个重儿子,其他的儿子全都是主元,所以就能表示出\(dp_{son_x}\)

复杂度\(O(N^3)\)

CF2045J Xorderable Array

对于限制,\(A_i\bigoplus p\leq A_j\bigoplus q\)\(A_i\bigoplus q\leq A_j\bigoplus p\),要异或上的东西涉及\(p\)\(q\),导致式子很麻烦

所以变换一下,设\(b_i=A_i\bigoplus p\)\(t=p\bigoplus q\),则限制就变成了\(b_i\leq b_j\bigoplus t\)\(b_i\bigoplus t\leq b_j\),已经简易多了

现在枚举\(p\),看哪些\(t\)合法,比较大小显然从高往低位

  • 若当前位\(t\)\(0\),则必须把\(b_i\)在这一位是\(0\)的放前面
  • 若当前位\(t\)\(1\),此时\(b_i\)在这一位不能有相同的值,无其余限制

我们称每一层还放到一起的那些数的集合为等价类

发现每一层的划分只和\(b_i\)在这一位是否相同有关,即完全可以用\(A_i\)替代\(b_i\)进行这个操作,那么就没有必要枚举\(p\)

进一步的,对于\(t\)当前位为\(1\)时,此时每个等价类的大小都必须\(\leq 2\),且显然无论何时,每个等价类都是把\(A_i\)排序后的一段区间

所以可以一开始先确定前\(d\)层的\(t\)必须是\(0\),且进行完\(d\)层操作后,才会导致所有等价类大小\(\leq 2\)

此时把大小\(\geq 2\)的等价类的\(i\)\(i+1\)(排序后)的\(A_i\bigoplus A_{i+1}\)存到集合\(S\)

考虑当前\(S\)中剩余的数在当前层的值

  • 存在\(0\),此时\(t\)在这一位只能是\(0\),然后所有\(S\)中在这一位是\(1\)的就被扔了
  • 都是\(1\)
    • \(t\)在该位是\(0\),那么\(S\)直接清空,\(t\)后面的位就随便填了
    • \(t\)在该位是\(1\),那么\(S\)不变

若建一个\(0/1trie\),合法的\(t\)就是从跟走到叶子的一条路径,其中可能某个节点的不在路径上的那个子树的全部点也都可以选

可以发现,这也代表着\(t\leq\min\{A_i\bigoplus A_{i+1}\}\)

那么方案数就是简单的了

\(N\)\(Q\)同阶,复杂度\(O(NlogN)\)

P4704 ✩✯

显然直线和圆的交点会选在圆的两个结点的中心,然后和这条直线相交的线段是那些两个端点不在被该直线划分出来的两个弧的同一个弧的

发现对直线直接考虑怎么放不好做,转为考虑直线和圆的那些交点

显然对每条线段,被它划分的两个弧里都至少要有一个交点,发现只要满足这个条件,然后若点有\(k\)个,连\(\lceil\frac k2\rceil\)条直线就好(就把点顺时针排序后,一个点连它对面的点)

拆环为链,如果是序列,那么就是贪心,找到最前面的\(r_i\)即可,但是拆环成的链就有点问题,那么可以考虑枚举断开的地方,并钦定它这里是一个交点,然后倍增的跳就好

这样是\(O(NlogN)\)

但是可以做到线性的,考虑所有限制区间中最短的那个,设它的长为\(d\),注意到所有的关键点间的距离都\(\geq d\),也就是说,我们可以一边枚举这个最短区间中的那个关键点,然后再\(O(\frac nd)\)的模拟贪心的过程

总复杂度就\(O(N)\)

CF1693F

这道题比较经典吧

首先显然每次操作都会有\(c_0=c_1\)

那么根据当前是\(0\)还是\(1\)更多,以\(0\)更多为例,找到最末尾的\(0\),然后找到最长后缀满足后缀中\(c_0=c_1\),然后操作

可以\(O(NlogN)\)

当然也可以把前缀和存下来,然后实时维护一下

可以做到\(O(N)\)

CF1329E ✩✯

一开始一直在想构造的方式,但是并没有太多进展

这种就转换思路,考虑怎样的\((L,R)\)合法,显然它的充要条件是:

  • \(\forall i\)\(\lceil\frac{c_i}R\rceil-1\leq\lfloor\frac{c_i}L\rfloor-1\)
  • \(m+\sum\lceil\frac{c_i}R\rceil\leq k\leq m+\sum\lfloor\frac{c_i}L\rfloor\)

剩下的就简单了,显然对于第二个条件,能得到\(L\)的上界\(L_0\)\(R\)的下界\(R_0\)

  • \(L_0\geq R_0\)

    此时答案一定为\(0\),取任意\(L=R\in[R_0,L_0]\),因为\(\sum\lceil\frac{c_i}R\rceil\leq\sum\lfloor\frac{c_i}L\rfloor\),且\(\lceil\frac{c_i}R\rceil\geq\lfloor\frac{c_i}L\rfloor\),所以一定有\(\lceil\frac{c_i}R\rceil=\lfloor\frac{c_i}L\rfloor\)

  • \(L_0<R_0\)

    因为\(-1+\lceil\frac{c_i}R\rceil\leq\lfloor\frac{c_i}L\rfloor\),且当\(-1+\lceil\frac{c_i}R\rceil=\lfloor\frac{c_i}L\rfloor\)就不合法了,所以对于每个点\(i\),都会有组限制\((u_i,v_i)\),表示\(L\leq u_i\)\(R\geq v_i\)至少要满足一个

    要求把所有二元组分成两组\(S\)\(T\),使得\(\max_{i\in T}v_i-\min_{i\in S}u_i\)最小,显然可以按\(u_i\)排序后从大到小扫即可

复杂度\(O(NlogN)\)

CF1637H ✯✩

考虑选出的位置集合是\(S\),逆序对数量的减少量\(-\Delta=\sum_{i\notin S,j\in S,i<j}[p_i>p_j]-[p_i<p_j]\)

有一个重要的性质,对于任意逆序对\((i,j)\)\(i<j\&\&p_i>p_j\)),若把\(i\)选到\(S\)中了,也必须把\(j\)选到\(S\)

考虑证明:

为方便描述,把\((i,p_i)\)当作一个二维坐标上的点,那么以\((i,p_i)\)\((j,p_j)\)为中心划平行于坐标轴的直线,则其余所有点被分成了九个部分,从上到小,从左到右,标号为块\(1\sim 9\)

考虑每个部分在把\(S\)中的\(i\)替换成\(j\)后对答案的贡献

  • 首先把\(i\)替换成\(j\)本身就有\(-1\)的贡献

  • 对于四个角,块\(1,3,7,9\),显然无变化

  • 对于这个十字形的部分,发现只有块\(2\)\(S\)的部分和块\(8\)中不在\(S\)的部分产生的\(\Delta>0\)

    此时,我们采取这样的策略,一直把\(l\)往块\(2\)中在\(S\)的点跳,\(r\)一直往块\(8\)中不在\(S\)中的点跳,直到不能跳,此时把\(l\)替换成\(r\)一定不劣,然后再沿着这个跳的路径跳回来,再继续换

    显然这样就证得了我们的结论

有了这样一个结论后,再来考虑把总的贡献尽量拆分成\(S\)中每个点的贡献,设\(d_i=\sum_{j<i}[p_j>p_i]-[p_j<p_i]=i-1-2\sum_{j<i}[p_j<p_i]\),那么总的\(-\Delta=\sum_{i\in S}d_i-2\sum_{i,j\in S,j<i}[p_j>p_i]+\frac{|S|(|S|-1)}2\)

根据我们的性质,对于一个\(j\)\(\sum_{i,j\in S,j<i}[p_j>p_i]\)就是\(\sum_{j<i}[p_j>p_i]\),那么设\(d'_i=d_i-2\sum_{j>i}[p_i>p_j]\),答案就是选前\(k\)大的即可

这里能直接选前\(k\)大的,是因为,设\(v_i=2\sum_{j>i}[p_i>p_j]\),显然\(\sum v_i\geq inv(\{S\})\),所以如果选到的方案不合法,就会有\(>\)成立,也就是说算出的值比当前这个不合法的情况都不优,显然也不会优于合法的情况了,显然不优

复杂度\(O(NlogN)\)

CF1481F

设树高\(h\),显然最优情况是\(ans=h\),此时用背包判一下即可,用二进制分组可以做到\(O(N\sqrt N)\)

猜测其余情况就是\(ans=h+1\),构造方法是简单的:

遍历每一层,设\(a\)\(b\)的余量分别为\(r_a\)\(r_b\),若该层有\(k\)个非叶节点,则有\(2k\leq r_a+r_b\),取大的那个把\(k\)填满,然后尽量填满该层的叶子,如果填不满,就可以结束了,因为剩下的点都用另一种颜色填即可

GYM101221A ✩✬

我不会构造,玉玉

首先构造的\(trick\)就是尽量考虑递归到子问题去

手摸可以发现答案是\(n\),且它就是下界,考虑证明:

最终有\(2(n-1)\)个字符满足它们后一位和它相同,而每一次操作最多增加两个,第一次操作最多增加一个

考虑怎么构造,这个证明的方式也给我们提供了思路

显然实际有用的空位只有俩,那么现在就是 _ _ B A B A ... B A B A,把最后一个 A B放到前面去,变成 A B B A ...B _ _ A,再把第五位和第六位拿到空位上,变成 A B B A _ _ ... B B A A,对于中间的部分就可以递归处理了

AGC024E

发现每次插入的数,只要满足在它插入的位置后第一个和它的值不同的那个数的值小于它即可

又考虑到对于一段数值都相同的区间,任意顺序的插入会导致算重,所以钦定每次插到末尾

即我们只需要满足插入位置的后一个数值小于当前插入的这个树值即可

这种类型,显然考虑\(A_n\)的形态,再从\(A_n\)的形态考虑插入顺序的方案数

\(dp_{i,j}\)表示已经有\(i\)个数,插入了\(j\sim k\),转移考虑枚举\(j\)出现的第一个位置\(k\)以及时刻\(p\)

\(dp_{i,j}=\sum_k\sum_p dp_{k-1,j+1}\times dp_{i-k,j}\times C_{i-p}^{i-k}\)

\(\sum_p C_{i-p}^{i-k}\)预处理下就可以做到\(O(N^3)\)

AGC041F ✩✬

第一眼会想到要容斥,钦定\(S\)集合内的点一定不被覆盖

直接这样考虑没前途,发现对于\(S\)中的点,其所处的列一定不能放棋子,且注意到列都是连续的,所以转为枚举列的集合\(S\),表示\(S\)内的每个列中都会有一个被钦定不能覆盖的点

考虑每一个连续行,长度为\(len\),和\(S\)的交集大小为\(a\),则贡献如下:

  • \(a\)中的全都没被钦定,\(2^{len-a}\)
  • \(a\)中有被钦定的,\(\sum_{i=1}^a C_a^i(-1)^i=-[a>0]\)

但是注意到只是这样是可能会存在\(S\)中某一列中没有被钦定不被覆盖的点,所以再套一层容斥

枚举\(T\subset S\),表示\(T\)中的被钦定为 没有被钦定不被覆盖的点,\(T\)会带一个\((-1)^{|T|}\)的系数

还是考虑每一个连续行,长度为\(len\),和\(S\)的交集大小为\(a\),与\(T\)的交集大小为\(b\),则贡献如下:

  • \(a\)中的全都没被钦定,\(2^{len-a}\)
  • \(a\)中有被钦定的,\(\sum_{i=1}^{a-b} C_{a-b}^i(-1)^i=-[a-b>0]=-[a>b]\)

发现答案只与\(a\),以及\([a=b]\)有关,那么考虑从\((a,[a=b])\)这个二元组入手,得到代价,再乘上可能的\((S,T)\)的系数和

trick,反过来算,原本是\((S,T)\rightarrow (a,[a=b])\),现在变成\((a,[a=b])\rightarrow (S,T)\)

把棋盘划分成类似树形的样子(即每个连续行为一块,相同的连续行自然可以合并起来),发现点\(u\)\(a\)是儿子的\(a\)之和再加上\(u\)独有的列在\(S\)中的部分,\([a=b]\)是儿子的\([a=b]\)的并再并上\(u\)独有的列是否有\([a=b]\)

复杂度就是树形背包再加上代价的\(power\),复杂度\(O(N^2logN)\),可以预处理\(power\)使得复杂度为\(O(N^2)\)

ARC093F

直接计算很不好做啊,考虑容斥,钦定\(1\)的祖先中,\(S\)内的点都能打败\(1\)

朴素的\(dp\)就是设\(dp[s][t]\)\(t\)\(m\)中钦定用的点的集合,然后发现根本不用这样,直接设\(dp[s][i]\)表示当前\(m\)中钦定用的最小的点为\(i\)即可

复杂度\(O(2^NNM)\)

ARC100F ✩✯

首先容斥,用所有的序列的权值-不合法的序列的权值,前者就是\((n-m+1)k^{n-m}\)

对于后者,分为两个大类来处理:

  • \(A\)中的元素互不相同

    • \(|A|\geq k\),准确来说,是\(A\)中存在\(k\)的连续段使得区间内元素不相同,直接不用管了
    • \(|A|<k\),注意到无论\(A\)的具体形态如何,答案都是一样的,那么直接算出所有不合法的序列中包含了多少\(m\)长度的连续段满足段内所有点的颜色都不同,这个直接\(f[i][j]\)\(g[i][j]\),分别表示当前长度为\(i\),最长满足元素两两不同的后缀的长度为\(j\)的方案数和权值和
  • \(A\)中存在相同的元素

    此时,枚举\(A\)所处的位置,因为被\(A\)划分后空白的两段互不影响,所以直接先预处理\(dp\)的值,最后弄一下就好

复杂度\(O(NK)\)

这题主要就是要想到按\(A\)内是否有重复的元素来算

qoj5367

发现操作可以表示为,每次先操作\(root\)的子树,直到除了它的某一棵子树外,其余都空了,再递归进那棵子树进行同样的操作,且要保证,对于当前\(root\),不能让相邻的俩是同一棵子树里的

那么可以\(dp_{u,i}\)表示当前递归到\(u\),且\(u\)子树内剩余\(i\)个点没被操作,转移考虑设\(f_{k,i,j}\),表示操作了前\(k\)个子树,当前层共操作了\(i\)个点,钦定有\(j\)组相邻的是同一子树内的,转移的系数都是组合数

复杂度\(O(N^5)\),实际大大滴跑不满

[ROI 2017] 学习轨迹 ✯✩

首先答案的下界是两个序列的和的\(max\)

这说明,我们在两个序列中选的这两个子区间,至少有其中一个要满足它的区间和大于原序列和的一半,假设是\(a\)中的

那么找到\(a\)中第一个\(p\)满足\(p\)的前缀和大于\(a\)的总和的一半,则在\(a\)中选择的区间必定包含了\(p\)

这里很牛啊

现在对\(b\)扫描线右端点\(r\),维护左端点\(l\),显然\(r\)\(a\)中对应的位置会让\(a\)\(p\)所处的极大区间产生变化的,只有一个后缀,维护一下即可

复杂度\(O(NlogN)\)

ARC053D ✩✯

首先显然会想到,设\(f[i][j]\)表示\(a\)目前头是\(i\)\(b\)的头是\(j\)时,后续的\(c\)的方案数

转移有\(f[i][j]=f[i+1][j]+f[i][j+1]\)

发现当\(a_i=b_j\)时可能会重,考虑计算重复的情况

发现我们的操作可以弄到图上,即一个网格图,左上角是\((1,1)\),右下角是\((n,n)\),第\(i\)横行的边的值都是\(a_i\),第\(j\)竖列的值都是\(b_j\),操作就是每次往右或往下走,从\((1,1)\)走到\((n,n)\),两条路径不同当且仅当它们某一步经过的边的权值不同,求方案数

那么我们现在就在点\((i,j)\),可以发现,所有\(f[i+1][j]\)\(f[i][j+1]\)重复的路径,提出其中某两条,他们一定一个包含\((i+p,j+q)\),另一个就包含\((i+q,j+p)\),那么都一定会在某处\((i+k,j+k)\)重合,其中\(a_{i+k}=b_{j+k}\),且路径中所有相同权值的行和列,都一定相交在\((i,j)-(i+k,j+k)\)的线段上

那么枚举\(k\),中途要求不能相交,用卡特兰数即可

复杂度\(O(N^2)\).

[USACO24JAN] Merging Cells P

直接\(dp[l][r]\)表示\([l,r]\)的标号能留存到最终的答案,以\(dp[i][r]\)为例,转移有\(dp[i][r]\times\frac1{r-i}\rightarrow dp[l][r]\)\(sum_{i\sim l-1}\leq sum_{l\sim r}\)),显然前缀和/后缀和优化一下就好

复杂度\(O(N^2)\)

P9318 [EGOI 2022] Lego Wall / 乐高墙

根号分治啊

考虑以下两种做法:

容斥,钦定某些相邻的列不连通,这个复杂度\(O(W^2)\)

直接\(dp[i][j]\),表示现在前\(i\)列连通,且第\(i\)\(i+1\)列间有\(j\)个长度为\(2\)的积木横穿着,复杂度\(O(H^2W)\)

平衡一下,总复杂度\(O(N^{\frac43})\)

P10432 [JOISC 2024] 滑雪 2 (Day1)

分析一手可以得到,会增加\(h_i\)当且仅当\(\exists j\)\(h_j=h_i\&\& c_j\leq c_i\)\(h_i+1\)后可能继续升高,就用新的\(h_i\)为标准去看

一个点只要\(h_i++\)过,那么它就不可能会增加接口

那么说明有用的\(h\)(有特殊操作,如加入一些点,或增加接口)就只有\(O(2N)\)\(h_i\)\(h_{i+1}\))个,考虑\(dp[i][j][k]\),表示当前考虑离散化后的高度\(i\),有\(j\)个点要上升到高度\(i+1\),留了\(k\)个接口

当然这里可能有的实现把加入接口直接就立刻加入的话,可能可以做到只需要把\(h_i\)压入状态中即可

同高度的点显然只会取\(c\)最大的\(j\)个往后放

复杂度\(O(N^3)\)

P10197 [USACO24FEB] Minimum Sum of Maximums P

考虑这样一个情况,若只钦定了\(a_1\)\(a_n\),此时最优该怎么办

钦定\(a_1\leq a_n\),权值\(\sum_{i=1}^{n-1}\max(a_i,a_{i+1})=\sum_{i=1}^{n-1}a_i+\max(0,a_{i+1}-a_i)\),显然最优情况就是区间和(除去\(a_n\))+最大值-最小值,只需要将\(a_{2\sim n-1}\)从小到大排即可

对于\(a_1\geq a_n\)的情况倒过来即可

再考虑到这样一个性质,所有相邻关键点的区间包含的点的值域(除了关键点),要么包含,要么不交

那么直接\(dp[l][r][s]\),表示区间\([l,r]\)能填满\(S\)中的区间的最优答案,转移是简单的

复杂度\(O(N^23^K)\)

【NOIP Round #5】青鱼和区间 ✯

题目的要求等价于,对每个点\(i\)记录一个\(s_i\),表示覆盖了\(i\)的区间的集合,那么就要求所有的\(s_i\)互不相同

对于不合法的,即存在\(s_i\)相同的,我们考虑两对点\((i,j)\)\((a,b)\),满足\(s_i=s_j\)\(s_a=s_b\),那么\((i,j)\)\((a,b)\)满足,要么包含,要么不交

这里我一开始一直在想区间\(dp\)啊,但是是从二项式反演那方面入手,容斥的很怪,反正就是得不到二项式反演的形式(

发现其实做麻烦了,原本的想法是,对于所有\(s_i\)相同的都要在区间\(dp\)的转移中作为端点存在,这样很麻烦,考虑只把\(s_i\)相等的那些点的最小和最大的,记做\(l\)\(r\)点作为\(dp\)转移中的端点存在,然后\([l+1,r-1]\)内部的点的边随便连

这样我们的序列\([1,n]\)就分成了很多块,设有\(k\)块,显然要求是\(k=n\),假设已经求出\(k<n\)时的答案\(ans[k]\),那么只需要用\(ans[k]\)乘上我们的划分方案,发现这是一个不合法的方案数,且所有\(k\)对应的方案数不重

复杂度\(O(N^3)\)

其实正解就相当于只保留了我原本想的那种\(dp\)的最外层啊,还是要多想一下转移有没有弄复杂

【NOIP Round #5】青鱼和怪兽/[ARC016D] 軍艦ゲーム ✩

思路差不多,就用前面这个举例

转移设\(dp[i][j]\)为玩家\(i\)点,怪兽\(j\)点时的期望时间

转移\(dp[i][j]=\min(dp[n][m],p\times dp[i][j-1]+(1-p)\times dp[i-1][j])\),其中\(dp[0][i]=dp[n][m]\)\(dp[i][0]=0\)

发现转移会在\(dp[n][m]\)处成环,这里有个经典\(trick\),就是直接二分\(dp[n][m]\)的值为\(x\),根据这个\(x\)得到的\(dp[n][m]\)称为\(f(x)\),显然\(f'(x)\leq 1\),那么\([f(x)-x]'\leq 0\),也即可以二分得到\(x\)

复杂度\(O(NMlogV)\)

D2 - Club of Young Aircraft Builders (hard version)

对于\(easy\)版本的,是\(a_i\)都是\(0\)的情况,直接\(dp[i][j]\)表示\(i\sim n\)填了\(j\)个即可

现在有些位置上的\(a_i\)有具体的限制了,就不能直接这样,考虑转换一下题目的限制

发现设\(cnt_i\)表示\(\leq i\)的数放了\(i\)个,那么只需要所有\(i\)都在\([1,c+\sum_{j<i} cnt_j]\)即可

那么\(dp[i][j]\)表示\(\sum_{k\leq i}cnt_k =j\)即可

\(N、C、M\)同阶,复杂度\(O(N^3)\)

CF865D Buy Low Sell High ✩

反悔贪心经典题,比较简单吧,看到谁在发就看了一眼

考虑这样一个贪心,要求当前点\(x\)作为卖出的时刻,那么就会选前面剩下的点中最小的作为买入的,即一个堆维护

那么每次遍历到\(x\)就往堆里塞入\(a_x\),如果\(x\)可以作为卖的,再塞入一个\(a_x\)作为反悔用,选了这个就代表用当前的\(x'\)代替\(x\)作为这一组的卖出方

复杂度\(O(NlogN)\)

AT_wtf22_day2_c Jewel Pairs ✩✬

感觉太牛了,感谢来自假Op的推荐喵

首先\(v_i+v_j\leq L\)的现在,经典的\(trick\)就是把\(\{v_i\}\)分成两类,一类是\(\leq\frac L2\)的,另一类是\(>\frac L2\)的,称前者为小点,后者为大点

显然小点内部非同色点可以任意匹配,大点只能和部分非同色小点匹配

有一个显然的性质,我们肯定是优先把小点和大点之间匹配了再去考虑匹配剩下的小点与小点

那么现在来考虑匹配小点和大点,设大点的\(u_i=L-v_i\),那么可以匹配的\(j\)要满足\(v_j\leq u_i\)

把所有的点按\(u_i/v_i\)的大小,从小到大排序,然后发现,若当前加入的大点\(i\)能和已加入且没被匹配的小点匹配,那么\(i\)就会在最终能匹配的大点集合\(S\)中,否则不在,因为\(u_i\)越小,也就意味这\(v_i\)越大,所以这样是正确的

直接判断\(i\)能否加入\(S\)是困难的,考虑\(hall\)定理,设\(N(S)\)表示\(S\)的邻域(即\(S\)中的大点能匹配的小点),那么最大匹配数就是\(|S|-\max_{T\subset S}(|T|-|N(T)|)\)

直接这样不好做,主要是因为还有颜色的限制,但是注意到,如果我们反着来,即维护\(T\)集合不能匹配到的点是简单的多的

所以有个很牛的转换,设\(F(T)=U/N(T)\),其中\(U\)是目前加入的所有小点的集合,那么最大匹配数也可以表示为\(|S|-\max_{T\subset S}(|T|-(|U|-|F(T)|))\)\(|S|+|U|-\max_{T\subset S}(|T|+|F(T)|)\),只需要计算\(\max_{T\subset S}(|T|+|F(T)|)\)即可

显然\(i\in T\),找到\(T\)\(u\)最大且\(c\)\(c_i\)不同的点\(p\),显然这个值就等同于:所有p及之前的大点+所有p之后c是c_i的所有点的数量

可以线性维护

再考虑小点怎么选,考虑求出\(f[c]\)表示颜色\(c\)的最少的不能被匹配的小点数量,发现这样一个性质,不管其他颜色的小点,直接把颜色为\(c\)的小点和\(S\)尽量的匹配,这个匹配数就是\(f[c]\),同样运用\(hall\)定理,解的出来要求的东西可以在把\(S\)中的大点和所有小点再进行一次上面的过程来求

对于这个性质的证明:

考虑反证,也就是说,要使得\(S\)中的大点都能匹配上的所有匹配方案中,都有\(c\)小点在最大匹配中能匹配上但在这里匹配不上的点

如果该点后面还有匹配向非\(c\)小点的非\(c\)大点,显然能直接让该大点和该\(c\)小点匹配,显然总是能找到的(先不考虑答案优不优的情况)

\(x\)为小点和大点匹配完后剩余的小点数

  • \(\max_c f[c] \leq\frac x2\)

    \(x\%2=1\),就扔一个点,现在就只考虑\(x\%2=0\)的情况

    此时小点大点匹配完后,若某一颜色的数量\(>\frac x2\),显然能一步步调整成恰好\(\frac x2\),然后就可以恰好全部匹配上了

  • \(\max_c f[c]>\frac x2\)

    \(y=\max_c f[c]\),那么最多的匹配对是\(x-y\),即有\(y-(x-y)\)个数无法匹配上

现在只用考虑怎么舍弃数最优,用舍弃大点类似的方式即可

复杂度\(O(NlogN)\)

ARC186A ◈✩

\(t1\)还是太先进

首先如果一个点\(A_{i,j}\)可以变成其他的值,其实就是找到所有的回路,满足回路的所有拐点\(0/1\)交替,然后拐点上的点就是可变化的

考虑涉及到行、列的性质,如果是网络流/二分图之类的题,就可以上二分图了

参考这个做法,如果\(A_{i,j}=0\),连边行\(i\rightarrow\)\(j\),否则行\(i\leftarrow\)\(j\)

上述的回路在二分图里也是以环的形式存在的,那么非环边的数量就是\(k\)

考虑\(dp[i][j][k]\),表示左边有\(i\)个点,右边有\(j\)个点,共有\(k\)个环边,因为显然经过某个点的所有环可以合并成一个大环,直接枚举\(p\)\(q\)表示新的环用了\(p\)个左部点\(q\)个右部点

复杂度\(O(\frac{N^6}w)\)

ARC186B

显然考虑连边\(i\rightarrow j\)表示\(p_i<p_j\),对\(DAG\)计数,显然想要把它变成树形的\(DAG\)

对于\(j\in (A_i,i)\),要有\(A_j\geq A_i\),也即包含关系

那么现在就形成了一块一块的,考虑当前新加入的\(i\),一直删除末尾的块直到当前块\(j\)满足\(a_j=a_i\),然后连边\(a_i\rightarrow i\)\(i\rightarrow j\),删除边\(a_j\rightarrow j\)

最后是一个树形的,直接组合数即可

我用了\(set\),复杂度\(O(NlogN)\)

ARC186C

先把\(P_i\geq V_i\)的箱子甩了,纯fvv

显然\(Alice\)每次会放当前有空位的盒子中没出现过的那个颜色的球,如果每次,每次\(Alice\)都会选容量最小的那个然后填满

箱子数量不够的情况可以单独考虑

考虑最后肯定是剩了\(m-1\)个只放了一个球的箱子,其他的放满了或不放,显然剩的是\(v\)最大的那几个,直接贪心即可

复杂度\(O(NlogN)\),瓶颈是排序

ARC186D

考虑合法的序列,就是满足:

  • \(\sum a_i=n-1\)
  • \(\forall i\)\(\sum_{j\leq i} a_j \leq i-1\)

后面这个可以转换成网格图走,然后不能碰到某一条线,简单的

枚举前缀和\(a\)相同的部分,再枚举下一位填什么,因为要满足序列和为\(n-1\),所以其实复杂度是\(O(N)\)

总复杂度\(O(N)\)


字符串

CF1827C

对于偶回文串,若它有一个偶的回文后缀,那么这个偶回文串一定能拆成若干个偶回文串

那么对于一个好的串的划分,采取能划分就划分的方式,则是唯一的

所以对于每个后缀找到最小的回文后缀即可

\(PAM\)即可\(O(N)\)解决问题

CF1913F

考虑改变\(s_i\)的字符,消失的回文串是不以\(i\)为中心,且包含了\(i\)的回文串,这个好算的

考虑改变后的,增加的也是不以\(i\)为中心且包含\(i\)的回文串

可以最开始先处理一下,枚举回文中心\(p\),可以很轻松的找到以\(p\)为o中心的最长回文串的长度,此时不能再长,要么是碰到边界了,要么当前两端的点的字符不相同,此时只需要改变其中一个变成另一个即可,我们假设它们已经相同,然后再继续延伸向两侧

复杂度\(O(NlogN)\)

P10716

对于\(k\)的限制,就是限制了\(|A|\)的最大长度,再加上\(A\)必须是\(border\),后面可以\(kmp\)+\(st\)表跳

前面这个是\(check\)是否串\(A\)\(S\)中贪心的匹配后,第\(k\)个匹配到的串全都包含在\(i\)内,因为一共匹配到的位置只有\(\sum\frac ni=O(NlogN)\),所以可以暴力的找到所有匹配的位置

具体的过程类似链表维护,维护当前点的后一个点,显然可以并查集辅助

复杂度\(O(NlogN\alpha(N))\)

P11150 ✩✯

要求\(S[1,i]+T+S[i+1,n]\)最小,暴力的想法就是枚举所有的\(i\)然后挨个判断大小,但这样复杂度高达\(O(TN)\),似了

考虑去掉无用的\(i\),对于点对\((i,j)\),若满足\(i+j\)最小且\(S[1,i]+T[1,j]<S[1,i+j]\),则显然这里的\(i\)可能成为答案的\(i\),否则当且仅当,前面得到的可能成为答案的\(i\)满足\(S[i-m+1,i]=T[1,j]\),即可置换一下\(S[i-m+1,i]\)\(T[1,j]\)的位置

因此可以在\(S\)后面塞个\(INF\)

可以\(SAM\)然后枚举\(j\)找最小的\(i\)即可,此时候选的\(i\)的数量级就是\(O(M)\)的了,可接受直接比较了

对于\((i_1,j_1)\)\((i_2,j_2)\)\(i_1<i_2\)),有\(S[1,i_1]+T[1,j_1-1]=S[1,i_2]+T[1,j_2-1]\),只需要考虑\(T[j_1,m]+S[i_1+1,n]\)\(T[j_2,m]+S[i_2+1,n]\)的大小即可,且可以发现,如果\(T[j_1,m]\)\(T[j_2,m]\)的前缀,那么其实\(T[j_1,m]+S[i_1+1,n]\)就和\(T[j_2,m]+S[i_2+1,n]\)相同了

求出可能是答案的\(i\)后,再往前跳\(T\)的循环即可

\(N\)\(Q\)同阶,复杂度\(O(Nlog N)\)


[NOI2021] 轻重边

做法1 ✩

比较巧妙的做法,给每个点赋值,然后一条边是重边当且仅当其相连的两点的权值相同

做法2

称题目的重边为标记边

先轻重链剖分,我们维护重链上的信息,轻链的把信息挂到父亲上,即记录一个点的孩子的轻边中,哪些是被标记的边,显然至多俩

那么跳\(a\rightarrow b\)时,因为与路径上的点相连且不在路进上的边中,只有\(O(logN)\)条重链,所以直接去修改这些重链

做法3 ✡

用毛毛虫,然后\(0/1\)表示\(x\rightarrow fa_x\)是否是重边

复杂度都是\(O(Nlog^2N)\)

《简单树剖练习题》

路径上的点的权值的变化就是\(2k|a_u-a_v|^m\),对于与路径相邻的那些重边,\(O(logN)\)条,直接暴力的改,轻边查询的时候暴力的查即可

复杂度\(O(Nlog^2N)\)

[QOJ9638] 线段树与区间加

做法1

其实\(va\)没用,因为\(a_i\)等价于\(\sum_{j\in tree_i} tag_j\times len_j\),那么给\(vb_i\)加上 所有祖先的\(va\)之和乘\(len_i\) 即可

发现操作就形如两条链,一个整体向左,一个整体向右,然后这两条链上的点除了最后一个,都要下传标记,且与链上的点(除了底部那个)相邻的点和链的底部的点都要打上\(k\)\(tag\)

树剖一下

这个打标记,对于重链头,就可以标记给它的父亲,后面遍历到它的时候再传下来即可,注意帮左/右儿子打的标记要分别记录

考虑怎么维护下传标记,实际上可以直接找到所有标记点然后传下去即可,因为你注意到每次实际上真正打到点上的标记是\(O(1)\)

复杂度\(O(Nlog^2N)\)

做法2

同样还是只保留\(vb\)

考虑每次\(pushdown(x)\)后答案的变化为\(lazy_x\times(-vb_x+vb_{ls_x}+vb_{rs_x})\),把\(vb'_x\)赋值为\(-vb_x+vb_{ls_x}+vb_{rs_x}\),记\(lazy'\)\(x\)到根的\(lazy\)之和,那么\(\Delta=\sum_{i\in S}lazy'_i\times vb'_i\)\(S\)表示要下传标记的集合

那么给一个点的\(lazy_x\)加上\(k\)的贡献就是\(k\times vb_x\),在每次操作中,只要找到所有打标记的点的\(vb_x\)之和即可,这个是好记录的,就像做法1一样,记录点\(u\)到其所属链底的所有点的非链上的左/右儿子的\(vb_x\)之和即可

对于每次操作,就是把完全被包含于\([l,r]\)的区间的\(lazy'\)都加上\(k\),与\([l,r]\)有交的区间的\(lazy'\)都清空且加入\(S\),后面这个是两个链,树剖很好维护

对于前面这个,注意到这样的点就是后面那俩链上的点的,不在链上的右/左儿子子树,考虑这样标号,对于一条重链,先把它链上的点都遍历了,再依次遍历其所有的左子树,再一次遍历其所有的右子树,这样就可以表示为一个区间了

复杂度\(O(Nlog^2N)\)

「GLR-R3」谷雨

用毛毛虫,但是端点处的点要特殊处理一下

复杂度\(O(Nlog^2N)\)

[集训队互测] 数据结构

毛毛虫升级版,也许可以叫猫猫虫

先标号一条重链,再依次标号距离该链长度为\(1\)\(2\)\(3\)的点即可

复杂度\(O(Nlog^2N)\)

[CF1930H]Interactive Mex Tree ✯✡

\(p_1\)是入栈顺序,\(p_2\)是出栈顺序,而\(mex(S)=min(U-S)\),则只需要得到所有不在路径\(x-y\)上的点的值的\(\min\)即可,设\(lca(x,y)=z\)\(x'\)\(y'\)分别表示\(x\)\(y\)处于\(z\)的哪个子树中,则\(U-S\)可以表示为:

  • \(p_{1,1\sim in[z]-1}\)
  • \(p_{1,in[y]+1\sim n}\)
  • \(p_{2,1\sim out[x]-1}\)
  • \(p_{1,in[x]+1\sim in[y']-1}\)
  • \(p_{2,out[x']+1\sim out[y]-1}\)
posted @ 2025-02-04 20:31  LuoyuSitfitw  阅读(80)  评论(0)    收藏  举报