2024.6

1. qoj8003 Anti-Plagiarism

不难想到 dp,即 \(dp_{x,a,b}\) 表示第一棵树以 \(x\) 为根的子树能否和第二棵树中以 \(a\) 为根时 \(b\) 的子树匹配,其中 \(a,b\) 相邻。

想想怎么转移,就是把子树的 dp 值算出来,然后对于 \(x\) ,枚举一对 \(a,b\) ,发现这里其实就是二分图匹配:右边的点是 \(x\) 的儿子,左边的点是 \(b\) 除了 \(a\) 以外与之相邻的 \(c\) 。然后如果 \(dp_{v,b,c}=1\) 就从 \(v\)\(c\) 连边。看左边是否满流即可。最后再枚举一个 \(t\) ,进行类似的过程来 check 以 \(x\) 为根的子树是否和以 \(t\) 为根时的第二棵树匹配。

虽然直接这样复杂度是对的,但是常数巨大,难以通过。考虑我们计算出以 \(t\) 为根时做的匹配后,如果满了就直接输出 Yes 了;否则我们通过这个来计算所有 \(dp_{x,a,t}\) 的值:如果 \(a,x\) 代表的左部点不是最大匹配的必经点,就说明 \(dp_{x,a,t}=1\) 了。这是可以在 dinic 结束后顺便求得的。这样,我们做匹配的次数变成原来的 \(\frac{1}{3}\) ,容易通过。

2. qoj8005 Crossing the Border

一个 trick 吧。首先 \(O(3^n)\) 的 dp 是容易的,即 \(s_T\le W\)\(T\) 最高位大于 \(S\) 时用 \(dp_S\) 更新 \(dp_{S\cup T}\) 。考虑利用折半来优化这个过程,我们把状态表示成 \(LR\) 的形式,表示前 \(\frac{n}{2}\) 个状态拼起来和后 \(\frac{n}{2}\) 个物品的状态拼起来。核心思路就是:考虑在 \(LR'\) 处同时处理 \(LR\)\(L'R'\) 的转移,其中 \(L\)\(L'\) 的子集,\(R\)\(R'\) 的子集。

枚举 \(X\)\(Y\) ,如果 \(Y=0\) 就特殊处理一下;否则先枚举 \(Y\) 的子集 \(Y'\) ,其中 \(Y'\) 不能包含 \(Y\) 的最高位,把 \((s_{Y-Y'},dp_{XY'})\) 这个 pair 从小到大排序,并处理出前缀的信息和。

再枚举 \(X\) 的超集 \(X'\) ,找到第一个值 \(\le W-s_{X'-X}\) 的前缀,用相应的信息更新 \(dp_{X'Y}\) 即可。注意到这里我们可以预处理出 \(s_{Y-Y'}/s_{X'-X}\) 排序的结果,所以复杂度即

\(O(6^{\frac{n}{2}}+3^{\frac{n}{2}}\log n)\)

3. qoj970 Best Subsequence

考虑二分答案 \(m\),把 \(\le\frac{m}{2}\) 的看成 \(1\)\(>\frac{m}{2}\) 的看成 \(0\) ,那可以发现 \(1\) 是会全部取的;对于 \(0\) ,考虑相邻两个 \(1\) 之间只能取至多一个 \(0\) ,我们尝试取其中最小的即可。

然后思考怎么快速的计算,首先 \(1\) 是容易的,可以主席树处理,对于 \(0\) ,设第一个 \(1\)\(x\) ,最后一个 \(1\)\(y\) ,我们先看 \(x,y\) 间的 \(0\) 有多少个被选的。仍然可以主席树处理:考虑 01 序列随着 \(m\) 的变化只会变化 \(n\) 次,考虑这个过程中所有存在过的相邻 \(1\) ,设这两端更大的为 \(X\) ,它们中间最小的数是 \(Y\) ,那么 \(m\in [X+Y,2Y)\) 时这一对数就能产生贡献。我们把这一对的贡献放到左边,仍然用主席树查就好了,即查 \(m\) 版本时 \([x,y)\) 的和,再加上 \(1\) 。最后是 \([x,y]\) 外的 \(0\) ,这里就单次的算即可。\(x,y\) 的位置线段树二分查即可。于是复杂度 \(O(q\log n\log V)\)

4. qoj971 Binary Search Tree

首先离线下来,利用扫描线转化成:对于一个序列,我们会单点修改,以及查询:对于某个位置 \(x\) ,找到序列建出的小根笛卡尔树中 \(x\) 最深的权值 \(\le v\) 的祖先 \(f\) ,并计算 \(f\) 到根的点的权值和。

很 ez,我们找到 \(i\le x\) 中最大的 \(i\) 使 \(a_i\le v\)\(i\geq x\) 同理,那么 \(f\) 就是两个位置中 \(a\) 更大的那个。这可以通过线段树二分计算;然后是计算 \(f\) 到根的点权和,你发现某个点 \(e\)\(f\) 的祖先等同于:\(e\)\(f\) 的最小值就是 \(a_e\) 。用单侧递归线段树就能计算这个东西了。

5. qoj8686 Zoo Management

其实就是分类讨论一下。对于每一个边双,考虑其中的点双,如果有个点双不是简单环就可以乱排了;否则,如果只是一个单独的简单环,判一下循环同构即可;否则,如果存在偶环就能乱排了;否则看一下排列奇偶性是否符合即可。

6. qoj1812 Interesting Coloring

求出 dfs 树,注意到是边双,如果每个点到根路径的不同颜色 \(<8\) ,那对于树边 \(e_1\),找到一个覆盖它的非树边 \(e_2\) ,把 \(e_2\)\(e_2\) 两端在树上的路径除掉 \(e_1\) 的部分拼起来即可;对于非树边 \(e_1\) ,取 \(e_1\) 两端在树上的路径即可。

你发现在范围内这是可以构造出的:记当前 \(1\)\(x\)\(c\) 个不同颜色,把儿子按 siz 排序,先尽量用前 \(c\) 种颜色,不能用了再用其他颜色,容易说明在 \(n\le 5555\) 的条件下这是一定合法的。

7. qoj1813 Joy with Permutations

对前 \(4\) 个数问 \(4\) 次中位数,若其排序后是 \(a_1,a_2,a_3,a_4\) ,我们就能得到 \(a_2,a_3\) 的值(记为 \(l,r\)) 以及 \(a_1,a_2\) 下标的集合(记为 \(i_1,i_2\)),\(a_3,a_4\) 下标的集合(记为 \(i_3,i_4\))。如果 \(n=4\) 的话你发现再用两次比较操作就得到答案了,我们尝试添加剩下的数并保持这个形式。现在加入 \(x\) ,查询 \(i_1,i_3,x\) 的中位数 \(m\),如果 \(l<m<r\) 说明 \(x=m\) 了,直接退出,否则我们不妨令 \(x\le l\)

如果 \(m=l\) 说明 \(a_{i_1}=l\) ,让 \(i_1:=x\) ,再计算新的 \(l\) ,算 \(i_2,i_3,x\) 的中位数即可。

否则,说明 \(a_{i_2}=l\) ,让 \(i_2:=x\)\(l:=m\) 即可。这样就做完了。

8. P8478 「GLR-R3」清明

\(\prod a'_i\) 拆开。即,\(a'_i=x_{i-m,i}+x_{i-m+1,i}+\dots+x_{i,i}\) ,我们枚举其中一个 \(x_{p_i,i}\) 即可。考虑所有情况下 \(\prod x_{p_i,i}\) 的和怎么算,记 \(s_i\) 是有多少个 \(p_x\) 的值等于 \(i\) ,令 \(g=\min(m,n-i)+1\) ,把 \(\tbinom{a_i+g-1}{s_i+g-1}\) 乘起来即可。

不难得到一个 \(O(2^mpoly(n,m))\) 的做法,即从 \(n\)\(1\) 枚举 \(i\) ,记录 \([i+1,i+m]\) 中哪些的 \(p\) 没有确定,然后每次选其一个子集把 \(i\) 填上,类似于子集卷积的优化即可做到 \(O(2^mm^2n)\)

尝试寻找 \(O(2^{n-m}poly(n,m))\) 的做法平衡复杂度,你发现我们不需要记录 \([1,m+1]\) 的状态,它们是本质相同的:转而记录其个数即可。复杂度就是 \(O(2^{n-m}m^3n)\)

平衡一下即可,复杂度 \(O(2^{\frac{n}{2}}n^{3.5})\),实际上 \(m\le 16\) 时用算法一,否则用算法二即可。

9. qoj5478 Quiz Contest

经典问题。相当于有多项式 \(F_i,G_i\) 满足 \(G_i\) 项数 \(\le F_i\) 且所有 \(F_i\) 的项数和 \(=m\) ,对于 \(i=1,2,\dots,n\)\(\sum h_k [x^k](G_i\prod\limits_{j\neq i}F_j)\)

考虑分治 NTT,求出每个节点的 \(F\) 的乘积。然后考虑 \(solve([l,r],H)\) 表示 \([l,r]\) 的答案都可以表示成 \(\sum h_k[x^k](G_i\prod\limits_{j\neq i,l\le j\le r}F_j)\) 的形式。递归下去即可,即 \(solve([l,mid],H/F(mid+1,r)),sol([mid+1,r],H/F(l,mid))\) ,这里的 '/' 是差卷积。保留有效的项数即可。复杂度 \(O(m\log ^2m)\)

10. qoj2070 Heavy Stones

先想想暴力怎么写,这其实就是形如两条链的树做 exchange argument。

想想怎么优化,你考虑对两边分别把能往上合并的部分合并了,再合并两边的结果,即如果一个段的平均数小于其父亲的段的平均数,就给这两段合并了。考虑 \(i\) 增大时前缀的段的变化,不难发现变化段数是均摊 \(O(1)\) 的,每次是删除栈尾的一些段再加入一段。那其实后缀的段的变化也是 \(O(1)\) 的。于是把所有出现过的段离散化下来,用线段树维护对两边合并的结果就好了。复杂度 \(O(n\log n)\)

11. qoj8683 Bridging the Gap

先分析一下我们走的形式,有以下三种运法:

运满 \(m\) 个人,其中有一些不动了,有一些以后为了拿手电筒会返回;

\(<m\) 个人,这些人之后全都会返回;

把所有人都运过去且不返回。

其中不动了的人我们会取权值尽量大的,回去的人会取尽量小的。现在假设我们已经确定了每次运的人数以及要回去的人数形成的二元组 \((a_1,b_1),(a_2,b_2),\dots,(a_k,b_k)\) ,那首先 \(\sum (b_i-1)=-1\) ;其次我们直接令其费用为:\(\sum\limits_{i=1}^k s_{b_i}+t_{n-\sum\limits_{j=1}^{i-1} a_j}\) ,其中 \(s\)\(t\) 的前缀和。考虑这样为什么是对的,先说明其合法性,虽然确定了每次运的人,但我们完全可以编排这些二元组的顺序,令一个二元组的权值是 \(b_i-1\) ,我们在每个权值 \(x>0\) 的二元组后接 \(x\)\(-1\) 即可,再把剩下的 \(-1\) 接到最后。每个 \(-1\) 就使用它前面那个二元组中产生的要返回的人。然后不难说明这是不劣的。

对着这个 dp 就好了,设 \(dp_{i,j}\) 是只考虑第一种,第三种运法使得 \(\sum a=n,\sum (b-1)=j\) 的最小代价,在令 \(f_i\) 是考虑第二种运法的最小代价,那么答案即为 \(\min\limits_{j\geq 0} f_j+dp_{n,-1-j}\) 。直接算 dp 的值是 \(O(n^3)\) 的,注意到 \(|j|\le \frac{n}{m}\) 且每次转移 \(O(m)\) ,复杂度即降至 \(O(n^2)\)

12. CF1912C Cactus Transformation

题意是给一个仙人掌,每次可以删一条边加一条边,要求得到的还是仙人掌,要构造方案把它变成另一个给定的仙人掌。\(n\le 1000\) ,要求步数 15000 以内。

先判无解,如果该仙人掌满足 \(n\) 为奇数且 \(m=\frac{3}{2}(n-1)\) 就不能操作了,此时直接判两个图是否相同即可。

否则,由于操作可以可逆,尝试把这个仙人掌变成一个特定的结构较简单的图。考虑把其变成一个类似于菊花图的样子:点 \(1\) 上面挂了三元环 \((1,2,3),(1,4,5),\dots,(1,2k,2k+1)\) 以及一些边 \((1,2k+2),(1,2k+3),\dots ,(1,n)\)

先把图简化,长度 \(>3\) 的环都容易改成三元环;对于不与 \(1\) 相连的割边 \((u,v)\) ,删 \((u,v)\)\((1,v)\) 。然后考虑每次取一个与 \(1\) 相连的点 \(x\) 使其度数 \(>2\) ,那么有两种情况:

  1. \((1,x)\) 为割边,取 \(x\) 所在三元环 \((x,y,z)\) ,割 \((y,z)\)\((1,y)\) ,割 \((x,z)\)\((1,z)\)

  2. 不为割边,那么有三元环 \((1,x,a)\) ,考虑取一度数为 \(1\) 且与 \(1\) 相连的点 \(b\) ,割 \((x,a)\)\((a,b)\) 。注意这里就出现了割边 \((1,x)\)

我们优先找第一种点。那你发现两步以内就能使 \(1\) 度数 +2 。\(1\) 度数 =n-1 时肯定结束了,否则一定能找到这样的 \(x\) 的,那么就做完了。

13. uoj700 可爱多的字符串

我们要算的大概是 \(\sum\limits_{i=l+1}^r w_{\min(r,i+lcp(i,l)-1)}\)

对反串建 sam 并在 fail 树上树剖。字符集是 \(\{0,1\}\) 所以这个树是二叉树,在后面会帮到我们。

在每条重链上统计 \(i,l\) 代表的点的 lca 在这条链上时的贡献,令 \(d_i\)\(i\) 代表的点往上遇到的第一个重链上的点的 len 值, \(d_i=d_l\) 时,由于是二叉树,只有 \(i\)\(l\) 为重链上的点才合法,这个直接算就好了;现在只考虑 \(d_i\neq d_l\) 的情况。发现 \(lcp(i,l)=\min(d_i,d_l)\) ,那就可以把上面的式子写成 \(\min(r,i+d_i-1,i+d_l-1)\)

先考虑 \(i+d_l-1\) 为最小值的情况,这个时候 \(d_i>d_l\) ,我们枚举重链上的每个点 \(u\),再枚举其轻子树上的挂的询问,此时 \(i\) 一定在 \(u\) 的重儿子 \(t\) 的子树内,所以所有可能的 \(i+d_l-1\) 其实是节点 \(t\) 代表的最短串的所有出现位置的右端点 -1 的结果。

考虑建出正串的 sam 并找到这个最短串对应的节点,于是问题变成这个节点的所有在 \((l+d_l,\min(r+1,r+d_l)]\) 的 endpos 的权值和,这容易排 dfn 转二维数点解决。

再考虑 \(i+d_l-1\le r\)\(d_i<d_l\) 的部分,直接二维数点做完。

再考虑 \(i+d_l-1>r\) 的部分,相当于 \(w_{\min(r,i+d_i-1)}\) 的和。仍然二维数点做完,不过注意要减去 \(d_i=d_l\) 的贡献。

复杂度 \(O(n\log^2n)\)

14. 6.4 T3

题意是给你 \(n,x,y\) ,问所有可以表示成 \(a^xb^y\)\(ab\le n\) 的数的和。\(x,y\le 10,n\le 10^{12}\)

判掉 \(x=y\) 后,不妨令 \(x<y\) 。如果一对 \(a,b\) 满足,在某个质数 \(p\)\(a\) 的次数 \(\geq \frac{lcm(x,y)}{x}\) ,那它就是不优的:我们可以让 \(a\) 除掉 \(p^{lcm(x,y)/x}\) 并让 \(b\) 乘上 \(p^{lcm(x,y)/y}\) 。不难发现合法的 \(a,b\) 对应了唯一的数,于是问题转化成,所有满足 \(ab\le n\)\(a\) 质因数分解后次数都小于 \(k=\frac{lcm(x,y)}{x}\)\(a^xb^y\) 之和。

容斥处理这个东西,得到答案为 \(\sum\limits_{d}d^k\mu(d)F(\frac{n}{d^k})\) ,其中 \(F(n)\) 是所有 \(ab\le n\) 的对的 \(a^xb^y\) 之和,这在预处理所有 \([\frac{n}{i}]\)\(i^x,i^y\) 的前缀和后即可 \(O(\sqrt{n})\) 得到。于是复杂度是 \(O(\sum \sqrt{\frac{n}{d^k}})\)\(k=2\) 时等同于 \(O(\sqrt{n}\log n)\) ,否则一定更快。预处理通过拉插可以做到 \(O((x+y)\sqrt{n})\)

15. qoj6299 Binary String

你发现 01 交替的部分都是比较稳定的,于是不妨分析所有大于 \(1\) 的连续段,手玩一下可以发现每次 0 连续段会往左移,1 连续段会往右移,撞上的时候长度会各自减 \(1\) 。剩下的过程就比较容易了。

16. qoj6304 Rectangle

只考虑一 \(x\)\(y\) 的情况,其余都是对称或容易的。对 \(x\) 轴扫描线,那么问题变成:每次加入/删除一个线段,同时查询取两个点覆盖所有线段的方案数。

分析一下,不妨计算第一个点位置 \(\le A=\min r\) ,第二个点 \(\geq B=\max l\) 的方案数,若 \(A\geq B\) 再减掉 \(\tbinom{B-A+2}{2}\) 即可。

考虑第一个点的位置 \(x\) 对第二个点 \(y\) 的限制,对于一个线段 \([l,r]\) 我们已经让 \(x\le r,y\geq l\) 了,所以只是当 \(x<l\) 时会有 \(y\le r\) 的限制。

考虑维护一个序列 \(b_x\) ,表示所有满足 \(x=l-1\) 的线段的 \(r\) 最小值,那么 \(x\)\(y\) 就需要 \(\geq B\)\(\le\) \(b\) 的后缀 min 。不难通过线段树二分算出合法的 \(x\) 的区间。现在相当于是,设 \(c\)\(b\) 的后缀 min 数组,要算 \(c\) 的区间和,这可以用单侧递归的技巧维护。当然这里只是方便陈述,实际上得先离散化下来,计算的时候就稍微有点区别。

复杂度 \(O(n\log^2n)\)

17.qoj7610 Bus Lines

\(g_x\) 是覆盖 \((x,fa_x)\) 的路径中最浅的 lca。考虑怎么计算 \(f(i,j)\) ,记它们的 \(lca\)\(p\) ,我们让两端各自从 \(u\) 跳到 \(g_u\) ,直到深度 \(\le p\) ,但这样可能算大了一步:如果 \(i\neq p,j\neq p\) ,记 \(i'\)\(i\) 往上跳最后一个深度 \(>p\) 的点,\(j'\) 同理,那如果有路径同时经过 \((i',j')\) 答案就减 \(1\) 了。

现在考虑统计答案,第一部分虽然比较繁琐但还是简单的,关键在第二部分,考虑从下往上枚举 \(p\) 以及 \(p\) 的儿子 \(v\) ,计算 \(i\)\(v\) 内,\(j\)\(p\) 其他子树内的贡献。考虑此时所有 lca 为 \(p\) 且一端在 \(v\) 内的路径 \((X,Y)\) ,建出 \(X\) 的虚树,容易发现对虚树上的每一段我们只需计算:这一段子树内对应的所有 \(Y\) 到根的并的区域的权值和,其中此时一个点 \(x\) 的权值是:有多少 \(u\) 满足不跳到 \(p\) 以上最高能跳到 \(x\) 。写成一个 \(\sum F(u_i)-\sum F(lca(u_i,u_{i+1}))\) 的形式,其中 \(F(u)\)\(u\) 到根的权值和,这可以 BIT 维护;合并子树的信息可以线段树合并。这就做完了。复杂度 \(O(n\log n)\)

18.学习 miller-rabin

先把 \(n-1\) 写成 \(a*2^k\) (\(a\) 是奇数)。然后找一些质数 \(p\)(OI 范围内取前 \(12\) 个质数即可),如果 \(p^{a}\equiv 1\pmod n\) 就不管;否则我们看是否存在 \(j<k\) 使得 \(p^j\equiv n-1\pmod n\) ,不存在就寄了。

19.学习 pollard-rho

先判 \(n\) 是不是质数,是就结束,否则尝试找到 \(1<d<n\) 满足 \(d|n\) ,递归的分解 \(d\)\(\frac{n}{d}\)

考虑一个序列满足 \(f_n=(f_{n-1}^2+c)\bmod n\) ,其中 \(f_0\)\(c\) 是随的。这个序列是会出现循环节的,不过在随机条件下大概是 \(O(\sqrt{p})\) 级别的,其中 \(p\)\(n\) 的最小质因子。这里找循环节可以 floyd 判圈,其实就是找到第一个 \(f_i=f_{2i}\) 的地方。然后我们在过程不断看 \(gcd(n,|f_i-f_{2i}|)\) 是否大于 \(1\) ,大于 \(1\) 就可以结束了。否则我们重新随机 \(f_0\)\(c\)

但这样因为要多次求 gcd 是不够快的,一个优化是以 \(B=1,2,4,\dots,128,128,128,\dots\) 为块长,考虑对每一块把 \(\prod |f_i-f_{2i}| \bmod n\) 算出来,再看它和 \(n\) 的 gcd。这样就足够快了。要特判 \(n=4\) ,然后让 \(c,f_0\)\([3,n)\) 中随。

20.学习支配树

先跑出 dfs 树,不妨按 dfn 序重新编号。然后考虑求半支配点,点 \(x\) 的半支配点是最小的 \(k\) 满足存在 \(k\)\(x\) 的路径使除了 \(k\) 以外所有点 \(>x\) 。 求半支配点方法:找所有能一步到达 \(x\) 的点 \(v\) ,如果 \(v<x\) 就直接更新,否则找 \(v\) 在 dfs 树上所有 \(>x\) 的祖先(包括自己),用它们的半支配点更新 \(x\) 的支配点。这个我们 \(x\) 从大往小算,维护一个带权并查集即可。

找出半支配点后就容易找支配点了:保留 dfs 树的边,再从 \(x\) 的半支配点向 \(x\) 连边,按 DAG 求支配树的方法求即可,这里因为每个点就两个入度,所以是很好写的。复杂度 \(O(n\log n)\)

21. loj3001「JOISC 2015 Day 3」AAQQZ

先讨论对称中心不在被排序的区间内的情况,枚举 \([l,r]\) 使 \([l,r]\) 回文且被排序的区间右端点在 \(l-1\) (在另一端可以 reverse 了做)。那么此时要做的就是,有两个序列 \(A,B\),会让 \(A\) 的一个前缀从大往小排序,最后让 \(lcs(A,B)\) 最大。先考虑 \(lcs\le\) 排序前缀长度的情况,我们枚举这个 \(lcs\)\(t\) ,如果 \(B\) 不单调就结束了,否则维护一个 \(z\) 为最小的 \(z\) 使得 \(A[1,z]\) 的可重集包含 \(B[1,t]\) ,若存在 \(>B_t\) 的数 \(p\) 使得 \(A[1,z]\)\(p\) 的个数 \(>\) \(B[1,t]\) 就也结束了。否则用 \(t\) 更新答案。\(lcs>\) 排序前缀长度时,相当于枚举前缀长度,其实就是让上面的 \(z\) 恰好等于 \(t\) ,此时用 \(t+lcs(A[t+1:],B[t+1:])\) 更新答案即可。看看上面的过程,容易发现 \(a_{l-1}=a_{r+1}\)\([l,r]\) 贡献的答案不优,所以可能的 \([l,r]\) 只有 \(O(n)\) 对。

再讨论对称中心在被排序的区间的情况,可以发现我们的对称中心一定是最大值/最小值构成的区间的中心,否则可以调整,不妨令中心为最大值的中心,枚举右端点 \(r\)

\(r\)\(1\) 找到第一个 \(>a_{r+1}\) 的值,设其为 \(c\) ,可以发现我们取的区间中 \(>a_{r+1}\) 的值只能有 \(c\) ,否则就寄了,设 \(l\) 必须大于 \(L\)

类似上面的过程枚举 \(i=r+1,\dots,n\) ,如果 \(a_{i-1}<a_i\) 就结束,否则仍然是维护一个 \(z\) 为最大的 \(z\) 使得 \(a[z,r]\) 可重集包含 \(a[r+1,i]\) 。仍然先看最后组成的回文串不超出 \(l\) 的情况,那我们需要得知 \(l\) 最小是多少,以使包含的 \(c\) 尽量多,每次改变 \(i\) 时对 \(j\in[a_{i}+1,a_{i-1}]\) ,用 \(<z\) 的最大位置更新 \(L\) 即可,这容易 vector 实现。再看超出 \(l\) 的情况,先判一下 \(a_i\) 在两边出现次数是否相等,此时的 \(l\) 就需要 \(a[l,z)\) 都是 \(c\) 。直接枚举这些 \(l\) 就行,总量是 \(O(n)\) 的,预处理 \(lc_{i,j}\)\(R(a[1,i-1])\)\(a[j+1,n]\) 的 lcp ,用 \(2(lc_{l-1,i+1}+(i-r))+([l,r]内的 c 个数)\) 更新答案即可。

22. loj3274. 「JOISC 2020 Day2」变色龙之恋

先想一想 \(O(n^2)\) 做法。对于两个点 \(u,v\) ,我们称它们间有边当且仅当 \(u,v\) 一起开会时会出现一种颜色。

思考得到这个图后如何计算答案,显然此时每个点度数为 \(1\)\(3\) ,为 \(1\) 时与之相连的点一定与之同色。否则设相连的点是 \(a,b,c\) ,它自身是 \(x\) ,三个点与它的关系形如:一个点与它同色,一个点爱 \(x\)\(x\) 爱一个点,且不存在双向恋爱关系。 分别询问 \((x,a,b)\)\((x,b,c)\)\((x,a,c)\) ,不妨令 \(x\) 喜欢 \(c\) ,可以发现 \((x,b,c),(x,a,c)\) 都会返回 \(2\)\((x,a,b)\) 会返回 \(1\) 。这样我们就找出了 \(x\) 爱的点。找出所有不是双向恋的点所恋的点后,我们再来看 \(x\) ,此时我们已得知哪个点爱 \(x\) 了,我们便找出了与之同色的点。

于是问题变成如何在限定步数内得到这个图。可以发现很多点集,询问它得到的信息是很难用上的,原因是导致颜色个数变化的情况很多,难以分析。但你发现对于一个独立集 \(S\)\(Query(S)\) 一定等于 \(S\) ;对于 \(x\notin S\) ,若 \(S\cup\{x\}\) 不是独立集,则 \(Query(S\cup\{x\})\) 一定不等于 \(|S|+1\) ,事实上设 \(x\)\(S\) 的点间边数为 \(p\) ,则 \(Query\) 的值基本是 \(|S|+1-p\) ,只是喜欢 \(x\)\(x\) 喜欢的点同时在 \(S\) 时多减了 \(1\),但此时 \(p\geq 2\) ,于是性质仍然成立。

由于每个点度数都 \(\le 3\) ,再加上上面对简单情况下 query 值的分析,我们尝试拉出一个极大独立集 \(T\) ,可以发现 \(|T|\geq \frac{1}{4}{N}\) ,原因是 \(T\)\(U-T\) 间至多有 \(3|U-T|\) 条边,而至少有 \(|T|\) 条边。找出 \(T\)\(U-T\) 间的边,这个就枚举 \(U-T\) 中的每个点 \(u\),把 \(T\) 中的点排成一行,二分出最大的 \(x\) 使得 \(T[1,x]\)\(u\) 构成独立集,那么 \(u\)\(T_{x+1}\) 就存在一条边。再在 \([x+2,|T|]\) 上二分即可。二分前先 check 一下 \(T[l,r]\)\(u\) 是否构成独立集。

再令 \(U:=U-T\) 做下去即可。

接下来计算一下总询问次数,每条边都来了一次二分,即为 \(\frac{3}{2}{n\log n}\) ;最后还会多询问 \(3n\) 次,还是很够的了(这里 \(n\)\(2N\)) 。可以发现“二分前先 check 一下” 这一步很关键,省了很多次二分。

23.CF1616G Just Add an Edge

先想想怎么 check \(y\rightarrow x\) 是否合法,不妨在两侧加两个点 \(0\)\(n+1\) ,那首先看 \(0\) 能否只通过 \(i\rightarrow i+1\) 走到 \(x-1\)\(y+1\) 能否走到 \(n+1\)

再看能否取出两条不交路径,分别是 \(x-1\)\(y\)\(x\)\(y+1\) ,且覆盖了中间所有点。那这个 dp 一下就好了,记 \(dp_{i,j}\) 表示 \(i\) 在第 \(j\) 条路径,\(i+1\) 在另一条是否可行,转移是容易的。

考虑优化,令 \(L_u,R_u\) 是只看 \(i\rightarrow {i+1}\) 时能到 \(u\) 的最左点/\(u\) 能到的最右点,于是我们有 \(x\le R_0\)\(L_n-1\le y\) 。可以发现 \(R_0\)\(R_0+1\) 所在的路径一定是不相同的,于是考虑以 \((R_0,R_0+1)\) 为中心对两头分别做上面的 dp ,然后合并一下就好了。

24. qoj875 Arrange The Piranhas

观察 \(a\) 的前缀和 \(s\),可以发现每次操作要么使某个位置 +1 ,要么使全局 -1。那其实在每一个空位的操作次数就可以固定下来了:先计算 \(d_i\)\(b\) 的前 \(i\) 个数减去 \(a\) 的前 \(i\) 个数,令其中最小的为 \(x\) ,如果 \(x<0\) 则我们就使 \(d_0\)\(d_n\) 都加上 \(-x\) 即可。

接下来只需要判方案合不合法。很简单,每次找一个能操作且 \(d_i>0\) 的空位操作即可,首先这让两边的空位扩大了,其次虽然自己的空位变小了,但迟早也得变小的,严谨一点就是,对于一个合法操作序列,如果它第一步不是操作 \(i\) ,那就把从前往后第一个 \(i\) 移到最前面,显然依旧合法。现在只需要快速模拟这个过程,每次从前往后扫看有没有能操作的位置并尽全力操作。不太会分析这里的复杂度,但至少是很快的。

25. qoj2834 Nonsense

观察组合意义:对 \(n+1\) 个球染色,使得中间有一个绿球,左边有 \(a\) 个红球,右边有 \(b\) 个白球,且左边每个白球都会带来 \(x\) 的系数,右边每个白球带来 \(y\) 的系数。

\(F(n,a,b)\) 是此时的答案,那如果 \(a>0\) ,枚举最左边的球颜色是红/白即可得到 \(F(n,a,b)=F(n-1,a-1,b)+xF(n-1,a,b)\) ;否则枚举是绿/白即可得到

\(F(n,a,b)=\tbinom{n}{b}y^{n-b}+xF(n-1,a,b)\)

同理尝试枚举最右边的球颜色,我们也有 \(b>0\)\(F(n,a,b)=F(n-1,a,b-1)+yF(n-1,a,b)\) ,否则为 \(\tbinom{n}{a}x^{n-a}+yF(n-1,a,b)\)

对比两式,发现直接相减,我们即可由 \(F(n-1,a,b-1),F(n-1,a-1,b)\) 推到 \(F(n-1,a,b)\) 了,这个题就做完了。

另一种做法是注意到 \(F(n,a,b)=[z^{n-a-b}](\frac{1}{1-xz})^{a+1}(\frac{1}{1-yz})^{b+1}\) 。将其乘上 \((1-xz)+xz\)\((1-yz)+yz\) ,即可得到和上面类似的递推式。

26. qoj6842 Popcount Words

建出询问串的 AC 自动机,设 \(S_n=S_{n-1}+S'_{n-1}\) ,其中 \(S'\) 是指把 \(S\) flip 得到的结果。

那么文本串可以容易拆成 \(n\log V\)\(S_i\)\(S'_i\) 拼起来的形式。考虑设 \(f(u,n,0/1)\) 是节点 \(u\) 通过 \(S_n/S'_n\) 后转移到的节点,这个很容易算出来。再设 \(g(u,n,0/1)\) 为我们要对 \(u\) 通过 \(S_n/S'_n\) 的过程中的所有节点的权值加上这个 \(g(u,n,0/1)\) 。那这个也是容易算的。总之就是利用好文本串的递归性质。

值得一提的是这个文本串还有别的性质,一个很牛的性质是,对于 \(S_n\) 来讲,其所有 \(0\) 位置的 \(k\) 次方之和,与所有 \(1\) 位置的 \(k\) 次方之和是相等的。(P7468)

27. 6.26模拟 T3

题意是给定 01? 组成的串 \(S\) ,问有多少组 \((T_0,T_1,T_2,\dots,T_n)\) 使得 \(T_i\)\(T_{i-1}\) 插入 0/1 得到,且 \(T_n\)\(S\) 匹配。

很天才的题。思考如何计算一个固定串的答案,倒着看。如果我们看成:每次只能删一个连续段的末尾,这是不好处理的。一个天才的想法是,对 \(0\) 连续段只能删末尾,\(1\) 连续段只能删开头。那这样的话我们每次只能在 01 交界处进行操作,在这二者中选一个删掉。特别的在开头搞个 0,结尾搞个 1,且要求不能删除。

这还是不好处理。我们干脆不要只看固定串,就是说允许问号。那其实就是对于相邻两个字符,如果第一个是 0/? ,第二个是 1/? ,就能把它们合成为一个 ? 。因为此时我们确定了问号的值,所以这样弄是不重不漏的。

接下来就好处理了:设 \(p_i\) 是第 \(i\) 个字符和第 \(i+1\) 个字符合并到一起的时间,那你发现 \(S_i\) 就是对 \(p_{i-1}\)\(p_i\) 的大小关系的限制!问题完全变成了一个经典老题:LOJ575。复杂度 \(O(n\log^2n)\)

28. gym102201B Bohemian Rhaksody

不难转化成,取一个最大的在边框内的矩形,不严格包含给定点。把给定点对 \(x\) 排序,考虑 \(x\) 轴严格包含了点 \([l,r]\) ,那贡献就是,\((x_{r+1}-x_{l-1})\) 乘上,把 \(0,y_l,y_{l+1},\dots,y_r,M\) 排序后相邻之差的最大值。这里就有个 \(O(n^2)\) 做法:枚举 \(r\)\(l\)\(1\)\(r\) 推并利用链表更新这个值即可。

接下来考虑优化,我们分治,那么利用上面的方法就能从左右分别得到一个三元组集合 \((l,r,h)\) ,我们要做的就是从左右集合中各取一个三元组,求 \((h_i+h_j)(\min(r_i,r_j)-\max(l_i,l_j))\) 的最大值。但要注意这里的三元组集合有很好的性质:没有两组 \((l,r)\) 相交不包含,且对于 A 包含 B 的情况,A 的 h 小于 B 的 h 。

现在我们讨论 \((l_i,r_i)\)\((l_j,r_j)\) 是否有包含关系。有包含关系的情况很简单,就是二维偏序算一算。考虑不包含的情况,不妨令 \(l_i<l_j<r_i<r_j\)

进行第二次分治,计算 \(l_i<l_j\le mid<r_i<r_j\) 的最优结果,然后你发现不跨过 \(mid\) 的三元组就直接分治下去,否则的话,考虑左集合的三元组,若某个右集合的与它交在 \(mid-1\) ,那肯定同时交在 \(mid\) 了。于是只需分治到右边,右集合的分治到左边。

现在观察跨过 \(mid\) 的这些三元组,发现长得非常好看:对于随着 \(h\) 增大,\(l\) 增大,\(r\) 减小。

把左边的三元组按 \(h\) 从小到大排,右边的按 \(h\) 从大往小排,你发现两件事情:

如果不考虑包虑 \(l_i<l_j<r_i<r_j\) 的限制,这是具有决策单调性的;

对于右边的某个三元组,其在左边能取的三元组形成了往左移的滑动窗口。

你考虑如果这些窗口都交于一点 \(x\) ,那其实问题就不难了:对于 \(x\) 两侧,分别单调栈二分即可。虽然它们现在并不交于一点,我们可以贪心的划分这些窗口,使每一段的窗口都会交于一点,复杂度仍然正确。为什么呢,考虑每一段的开头 \(i_1,i_2,\dots,i_k\) 满足 \(R_{i_{j+1}}<L_{i_j}\) 。然后每一段的代价是 \(R_{i_j}-L_{i_{j+1}-1}<L_{i_{j-1}}-L_{i_{j+1}-1}\) 。求个和就能发现这个代价和是线性的了。

总复杂度 \(O(n\log^3n)\) 。教训:传参传 vector 全都写成引用,速度显著提高。

29. qoj5312 Levenshtein Distance

朴素的 dp 可以算 \(T\) 所有前缀与 \(S\) 的编辑距离,那不妨对 \(T\) 的每个后缀分别进行 dp 。思考编辑距离 \(\le k\) 带来了什么效果,首先 \(|i-j|\le k\) ,于是单次 dp 降为 \(O(nk)\) ,但这仍然是不优的,注意到这个 dp 的值有效范围也是 \(\le k\) 的,经典的,尝试交换值域和定义域,你观察到对于固定的 \(i-j=x\) 而言 \(f_{i,j}\) 是单调不降的,那我们就设 \(g_{x,y}\) 是满足 \(f_{i,j}\le y\)\(i-j=x\)\((i,j)\)\(i\) 最大者,转移就是令 \(a=g_{x,y},b=a+x+L-1\)\(L\) 是我们一开始枚举的后缀的左端点),枚举要不要跳过 \(a+1/b+1\) ,通过算 lcp 转移给 \(g_{x+1,y+z}\) \((-1\le z\le 1)\) 即可。这样状态就是 \(O(k^2)\) ,单次转移在用 SA 预处理 lcp 后是 \(O(1)\) 的。总复杂度 \(O(nk^2+n\log n)\)

30. qoj967 Rectangle Painting

类似于 loj3655 。复习一下这个东西:通过 ODT 来维护这个区间染色,观察每行的 \(0\) 连续段,每次会删掉一些加上一些,但均摊是 \(O(1)\) 的。然后你考虑对于每个段,把它拆到线段树上,就是在线段树每个节点维护一个 set 表示有哪些行的连续段会拆到这个节点上。我们可以设这个节点的权值是 set 中元素的 min ,然后再维护一个值是其子树内所有叶子到这个节点的权值 min 中最大的一个,这样查询就容易做了。

31. P9732 [CEOI2023] Trade

先想想怎么算答案,我们设一个区间的权值是前 \(k\)\(a\) 的和减掉 \(b\) 的和,我们要找最大的 \(f(l,r)\) ,不难发现 \(f\) 是满足四边形不等式的,那我们分治一下就算出来答案了。

接下来看怎么判一个位置在不在最优方案内,只需要找出所有 \(f(l,r)=ans\)\([l,r]\) ,算出区间内第 \(k\) 大值 \(z\) ,那 \([l,r]\) 内那些 \(a_i\geq z\) 的位置就都合法了,问题变成找 \([l,r]\) 。但你发现这样的 \([l,r]\) 数量可以卡到 \(O(n^2)\) ,怎么办呢。

神秘观察:考虑 \(f(a,d)=f(b,c)=ans\) ,其中 \(a<b<c<d\) 。那由于 \(f(a,c)+f(b,d)\geq f(a,d)+f(b,c)\)\(f(a,c),f(b,d)\le ans\) ,可以发现 \(f(a,c)=f(b,d)=ans\) 。而 \([a,c]\) 的第 \(k\) 大值肯定 $\geq $ \([a,d]\) 的第 \(k\) 大值,\([b,d]\) 同理,于是可以发现我们不需要用 \([a,d]\) 更新答案。

考虑分治的时候在值最大的前提下取 \(l\) 最大的,设其为 \(r\)。可以发现对于 \(r\) ,设上一个能得到的最大值的是 \(r'\) ,那你只需要扫一遍 \(l\in [p_{r'},p_r]\) 然后更新答案即可。复杂度 \(O(n\log^2n)\)

32.qoj2562 Fake Plastic Trees 2

暴力 dp 就是设 \(dp_{x,i,j}\) 是以 \(x\) 为根,子树内割了 \(i\) 条边,当前联通块权值和为 \(j\) 是否可能。

考虑优化,我们真的需要记下所有可能的 \(j\) 吗?想一想,我们只需要每个联通块在 \([L,R]\) 内就行了,那有没有方法能把一个 \(j\) 支配掉呢?

考虑三个数 \(x<y<z\) 。你发现如果 \(z-x\le R-L+1\) ,那 \(y\) 就能支配掉了:设选择了 \(y\) 之后最后形成的大小是 \(a\) ,那如果 \(a-y+z\le R\) 就替换成 \(z\) ,否则的话把 \(a-y+z\geq R+1\)\(x-z\geq L-R-1\) 两个式子加起来就能得到 \(a+x-y\geq L\) 了,所以就能把 \(y\) 替换成 \(x\)

再分析一下 \(j\) 的值域,由于已经割出的联通块大小总和在 \([iL,iR]\),可以得到可能的 \(j\) 的极差是 \(\le i(R-L)\) 的。

于是可以得到可能的 \(j\) 只有 \(O(K)\) 种,总复杂度 \(O(nK^3)\)

33.qoj5016 Range Minimum Element

不妨假设每个位置都被至少一个区间包含,设 \(h_i\) 是确定了 \(b\) 后包含 \(i\) 的区间对应的 \(b\) 的 max 。考虑知道 \(h\) 后能不能确定 \(b\) 的权值,发现是能的:找到 \(h\) 最小的所有位置,设其为 \(i_1,i_2,\dots,i_k\) ,那包含其中任意一个位置的区间的 \(b\) 就等于这个最小值了。剩下的区间权值一定大于最小值,递归的填 \(b\) 即可。当然这组 \(h\) 还可能不合法, 我们要求递归到的每个 \([l,r]\) 都满足:使用被 \([l,r]\) 包含的区间能覆盖完 \([l,r]\)

现在考虑 dp ,设 \(f_{l,r,k}\) 是有多少组合法的 \(h\) ,其最大值 \(\le k\) 。从小到大枚举 \(k\) ,再枚举 \(l\) ,转移是容易的,复杂度 \(O(n^3m)\) ,插一下就是 \(O(n^4)\)

posted @ 2024-06-04 22:38  grass8woc  阅读(207)  评论(1编辑  收藏  举报