2021-04 杂题泛做

Codeforces906E

一个朴素的 \(dp\),即 \(f_i\) 表示 \(i\) 之前翻成目标的最小步数,那么转移显然

\[f_i=\min_{S_{j+1\dots i}=T'_ {i\dots j+1}} f_j+1 \]

考虑一个和下题类似的构造:\(S=s_1t_1s_2t_2\dots s_{len}t_{len}\)

至此我们把问题转化成了最小回文划分,直接使用各种结论 \(dp\) 即可

Codeforces932G

首先用如下代码生成字符串 \(S\),其中 \(T\) 是输入给定

int l=1,r=T_len,c=0; while(l<=r) S[++c]=T[l++],S[++c]=T[r--]

其实这步构造是本题最不太好想到的一点

不难想到以前证明过的结论:一个串的回文后缀的长度可以放成 \(log\) 个等差数列

同时在 \(PAM\) 上面的 \(fail\) 是其的 \(border\)

首先得到一个 \(dp\) 也就是 \(f_i=\sum_{S[j+1\dots i]\texttt{是回文串}} f_j\)

那么考虑如何维护 \(log\) 段里面的和,也就是一些点的位置的 \(f\)

其实有一个思路是根号分治,公差 \(\le \sqrt n\) 的部分前缀和,反之暴力跑,复杂度 \(\Theta(n\sqrt n \log n)\),常数很小,但是完全不行

考虑这样一个前缀和函数 \(g_i\) 表示这个点对应在 \(PAM\) 上的 \(lst\) 的等差数列的和

每次跳回文树的时候维护最新的 \(g\),但是除了自己的 \(f_i\) 都不好做

观察 \(g_{fail[i]}\) 的具体含义,使用第二个结论发现它正好是所求,特判不是一个等差数列的情况跑暴力就行了

Hdu5390

心路历程很复杂,对着 \(\log^3\) 的做法卡了半天常,最后发现是线段树分治写挂了就很无奈

不难想到每个点的某种点权存在是一个区间,那么线段树分治维护每个点的点权

使用线段树分治之后,考虑把每个点的影响用 \(dfn\) 序放到子数的区间里面,对应的线段树套上 \(trie\)

回答询问在树套树上单点查询,沿路径找异或最大值

貌似卡常的方法如下:

\(1.\) 在线段树分的过程中,不断更新当前点代表的区间里面的询问的答案

不难发现这样需要每次清空一下树套树,那么 \(rt\) 赋成 \(0\),在树套树上下放就行

\(2.\) 线段树分治的时候如果 \(vector\)\(size\) 小于 \(30\log n\) 就暴力扫,因为树套树毕竟带着 \(600\) 的常数

\(3.\) 循环而不是递归实现异或最大值的查询和权值的插入

CF1276F

集合中本质不同的子串分为以下几种

  • 1.* 和空串 个数为 \(1\)

  • 2.a* 可以对 \(1\dots n-1\) 建一个 \(SAM\) 跑一下

  • 3.* a 可以对 \(2\dots n\) 建一个 \(SAM\) 跑一下

  • 4.a * b

不难得到的想法是维护每个点作为终止节点,求所有的 \(endpos\) 的并有几个本质不同子串

这个问题是一个经典问题,使用 \(SA\) 就是用 \(set\) 跑启发式合并,每次减掉 \(rk\) 相邻的两个点的 \(LCP\) 即可

还有一个做法是用 \(set\) 维护后缀树上的链并,可以考虑维护 \(dfn\) 序,相邻的点减掉 \(LCA\)\(len\) 也是可行的

Loj 毒瘤题

思路很阴间,主要运用了出现偶数次异或之后为 \(0\) 的性质

让输入的数去模一些质数,把异或和存到余数的位置上

对于出现次数很多的异或和,就表示可能是一个出现次数为奇数的数

这里注意不是出现次数为所选质数个数,因为没法保证所有答案模所有质数两两不同

那么正确性可以感性理解,出现偶数次的数肯定影响都消去了,那么出现奇数次的数不可能模任意若干个质数都一样

其实判出现次数大于 \(2\) 就过了

JSOI2019 节日庆典

前置:exkmp/Z_Function

定义 \(z_i\) 表示串 \(S\)\(i\) 开始的后缀和 \(S\)\(\mathrm{LCP}\),利用之前的信息先更新,后面跑暴力

对于多串匹配,设是 \(b\)\(a\) 的后缀的 \(\mathrm{LCP}\),那么先求 \(a\)\(Z\) 函数

性质:(未完)

对于一个既是原串前缀,又是原串后缀的串,其后缀出现位置的 \(z_i=n-i+1\)

没做过啥题,所以仍可以认为我不会


不是很好想到或者更根本想不到的一点是每个点的决策点很少,只有 \(\log n\)

证明其实并不复杂,考虑当前到了 \(i\),决策集合里面又一个点对 \(j>k\) 满足 \(i-j<j-k\)

画出图来发现这种情况必然会把中间的 \(j\) 毙掉,这里结合 \(border\) 和 周期 理解就行

实现的时候,先处理出来这个点的可能决策点,剩下的比较的形式都是一个后缀和整个串的比较

所以跑一个 \(exkmp\) 求出来比较即可

Loj6041 事情的相似度

题目转化为求一个区间里面所有前缀的最长后缀,也就是 \(ed_l\cdots ed_r\) 所有点两两在树上的 \(LCA\) 的深度的最大值

维护每个 \(r\) 可以匹配的每个深度的最大的 \(l\),使用扫描线配合树状数组来回答询问时一个可行的做法

但是这东西信息很多,能到 \(\Theta(n^2)\) 级别,但是不难发现每个点添加的时候维护左侧相邻的一定不劣

所以使用 \(set\) 维护 \(endpos\) 集合(或者线段树配合树上二分也可以),每次更新前驱后继的时候就加入到最后的信息

不难证明复杂度是 \(\Theta(n\log^2 n)\)

hdu6583

朴素的 \(dp\) 转移就是从前一个和从最短的包含这段串来转移

比较显然的两个观察就是 \(dp\) 数组单调不降,同时包含子串的 \(l\) 单调右移

维护指针 \(l\) 表示将 \(S[1\dots l]\) 加入后缀自动机能得到 \(S[(l+1)\dots i]\)

\(fail\) 可以找一段后缀(暴力复杂度正确),那么这样实现上面的 \(dp\) 即可

hdu6405

对于每个串更新的是本质不同子串的答案

那么暴力跳广义 \(SAM\) 上的 \(fail\) 并维护更新每个点的乘积

最后每个点对长度差分统计即可

回答询问之前预处理 \(26^k\) 的前缀和 和答案的前缀和,直接乘逆元就行了

下证该做法时间复杂度不超过 \(\Theta(n\sqrt n)\)

  • 长度超过 \(\sqrt n\) 串只有不超过 \(\sqrt n\) 个,即使遍历整个自动机,仍可以保证复杂度

  • 长度不超过 \(\sqrt n\) 的串每次遍历的点是 \(len^2\) 的,那么列等式 \(\frac{n}x \times x^2 =nx\) 仍能发现复杂度不超过 \(n\sqrt n\)

AGC004E

考虑题目中 “边界没有格子” 的条件

那么可以使用边界来维护两边的四联通,即左边一列给第一个,右边给第二个

偶数列给第一个,奇数列给第二个

剩下的交集都放就行了

其实是人类智慧题

十二省联考2019 异或粽子

建立可持久化 \(\texttt{0/1 trie}\) 将所有的点作为右端点放进一个堆

每次弹出元素直接再找一次最大值即可

复杂度 \(\Theta(n\log n)\),得把 #define int long long 删掉才能过

NOI2019 弹跳

二维平面上最短路,同时边是点向矩形,那么考虑使用 \(\mathrm{KD-Tree}\) 优化建图加 \(\mathrm{Dijkstra}\)

在最短路扩展的过程中进行了找最小距离的点,使用该点进行扩展,删掉该点

不难发现可以对应到 \(\mathrm{KD-Tree}\) 上的找全局最小点,进行矩形取最小值,删点的操作

那么先将所有给定点建树,维护矩形边界,最小距离即可

一个简单的优化是维护上矩形的最大距离,可以给矩形取 \(min\) 的时候剪枝

统一省选2020 作业题

使用 \(\varphi* I=Id\)\(gcd\) 拆开,那么就是对若干权值求有多少种方案的每条边都是其倍数,并统计其边权和

使用 \(Matrix-Tree\) 定理,每条边对应一个一次函数,那么行列式的值的一次项系数便是答案

仍然使用 \(Guass\) 求行列式,那么 mod-ans 就是 node(0,0)-ans1/a[i][i] 就是多项式的除法

考虑维护多项式的运算,因为只关心一次项,那么维护常数和一次项即可

四则运算中值得注意的除法, \(\frac{a+bx}{c+dx}\) 对应的是 \(\frac{a}c+\frac{bc-ad}{c^2}\)

这个运算的正确性使用多项式求逆的相关方法不难证明

Luogu4183

不难发现如果根到当前点的距离小于其子树里面最近的叶子到其的距离,那么这个子树需要 \(1\) 来保护

考虑如下结论:

一个点数为 \(m\) 的树里面有 \(\sum_{i=1}^{m} deg_i=2m-1\)

转化得到 \(\sum_{i=1}^m 2-deg_i=1\)

那么可以使用这样的东西来表示这个子树需要被保护,形式化地讲:

\[ans_x=\sum_{i=1}^n[dis(x,i)>mn[i]](2-deg[i]) \]

其中 \(mn[i]\) 表示距离其最近的叶子到其的距离

是树上路径问题,使用点分治统计即可,类似模板

Luogu4848

很套路的树套树,直接使用 \(\mathrm{KD-Tree}\) 维护平面,外层套权值线段树维护权值区间里面的信息

注意线段树第 \(i\) 个叶子是有多少个点上面有 \(i\)

对于修改,给一个单链上的树修改,查询直接线段树上二分,和二逼平衡树一题一样

posted @ 2021-04-05 21:32  yspm  阅读(108)  评论(0编辑  收藏  举报