CF1580D Subsequence
观察减法部分,可以发现可以用笛卡尔树+树形背包完成,每次合并节点 \(u\) 的两个儿子的时候,假设物品数分别为 \(i,j\) ,那么合并的答案显然要减去 \(2ija_u\) (这里乘二是因为每一对询问两次),如果要选上 \(u\) ,那么还需要减去 \(a_u \times (2\times \text{除 } u \text{ 以外选择的个数}+1)\) 。
[AGC009C] Division into Two
首先设定 \(A>B\) 。
观察性质,如果存在 \(i(1\leq i\leq n-2)\) ,有 \(a_{i+2}-a_i<B\) ,这时无论如何分 \(i,i+1,i+2\) ,都是不满足条件的。因此此时答案为 \(0\) 。
接下来用 \(\rm dp\) 解决,设 \(f(i)\) 表示考虑了前 \(i\) 个元素,其中强制令 \(i\) 放入集合 \(A\) 。显然这时候需要枚举上一个放入 \(A\) 的元素 \(j\) ,而这个 \(j\) 需要满足下面的条件:
- \(a_i-a_j\ge A\)
- \(\forall{p\in[j+1,i-2]\cap \mathbb{Z}}, a_{p+1}-a_p\ge B\)
第一个条件显然限制了 \(j\) 的最大值,而第二个条件限制了 \(j\) 的最小值,用前缀和维护一下 \(f\) 即可。
CF1299D Around the World
首先将和节点 \(1\) 相关的边都删掉,这样会有若干个联通块。
如果联通块和 \(1\) 只有一条边相连,因为路径权值是异或和,对联通块设一个线性基,接下来找到一颗生成树,然后将仅含一条非树边的环加入这个联通块的线性基中,可以认为任何一条从 \(1\) 到某个点然后再回到 \(1\) 的任何路径(包括不简单路径)都可以用树上路径配合若干个先前提到的环组成。(这个套路来自 \(\text{CF-938G Shortest Path Queries}\) ),而因为要回到 \(1\) ,所以树上路径的权值和为 \(0\) ,因此只需要看是否存在一些环是线性相关的。如果存在一些线性相关,那么这个联通块显然不能选。
如果联通块和 \(1\) 有两条边相连,那么实际上有两种情况:
- 选择其中一条边,可以发现这时候和先前完全一样,而且线性基和选择哪一条边无关。
- 选择两条边,那么这时候实际上是在线性基中加入了一个三元环(题目说只有三元环)。同理,这个三元环不能和之前的环线性相关。
接下来可以选择一些联通块,这个似乎做不了,因为线性基的数量过多?但是很多线性基实际上是一样的,将线性基消成最小的(将若干二进制数拼起来之后字典序最小),发现这时候只有不到 \(400\) 个不同线性基,那么就可以 \(\rm dp\) 了,要先预处理出两个线性基合并之后得到的线性基作为转移。
[HAOI2011]problem a
将每个人的信息 \((a_i,b_i)\) 转化一下,就是和他相同分数的区间为 \([a_i+1,n-b_i]\) 。
将相同的区间合并一下,合并之后的人数设为这个区间的权值 \(w[l,r]\) ,问题转化一下:选择不相交的若干区间,令选择的区间的权值和最大,这时候可以将区间按右端点排序,设 \(f(i)\) 表示考虑了前 \(i\) 个区间,强制选择第 \(i\) 个区间的最大权值和,那么有:
特别的,令 \(l_0=0,r_0=0\) 。
CF1540B Tree Array
首先枚举一个起始点 \(T\) ,接下来考虑一对数 \((i,j)(i>j)\) 对答案的贡献,这实际上是在求 \(i\) 在 \(j\) 之前被走到的概率,考虑当 \(\mathrm{lca}(i,j)\) 被走到之后的情况,这时候,除了这两个点到 \(\rm lca\) 的路径之外,其他的点都不用管,因为对答案的概率没有影响,显然有 \(\frac{1}{2}\) 的概率往其中一条路径拓展一次,那么有 \(f(i,j)\) 表示第一条路径先拓展 \(i\) 步,然后第二条路径才拓展了 \(j\) 的概率,可以得到:
那么 \((i,j)\) 的答案显然是 \(f[\mathrm{dep}(i)-\mathrm{dep(lca}(i,j)),\mathrm{dep}(j)-\mathrm{dep(lca}(i,j))]\) 。
[SDOI2019]移动金币
一个硬币向左移动 \(x\) 步实际上是将 \(x\) 个空格移到下一个硬币前,而硬币前的空格数可以看成石子数,这个问题就可以转化为某个博弈论经典问题:
有 \(n\) 堆式子,每个操作可以是选择第 \(i\) 堆式子中的若干石子,将其移到第 \(i-1\) 堆式子中,特别的,如果 \(i=1\) ,那么将选择的石子扔掉,不能操作者输。
这个问题可以将偶数位的石子堆忽略,当对手移动偶数堆的石子,你可以将对手移动的石子再移动一次。剩下的实际上就是将奇数位的石子堆看成一个 \(\rm Nim\) 游戏。
回到这一题,将棋子从右到左按 \(1\dots m\) 编号,变成经典问题了。
为了计算方案数,可以用总方案数(显然是 \(\binom{n}{m}\) ),减去必败的方案(奇数位置的异或和为 \(0\) )。
设 \(f(i,j)\) 表示考虑了前 \(i\) 个数位,当前用的总空格数为 \(j\) ,那么显然有:
最终合并答案的时候,有
Pro
\(n\leq 10^9, m\leq 8\times 10^3\)
观察上面的 \(f(i,j)\) ,实际上可以不关注 \(j\) ,而是关注选择的石子数总和前 \(i-1\) 位的进位,这时候只需要让每一位选择的石子堆都是偶数,并且和进位配合之后等于 \(n-m\) 的第 \(i\) 位即可,可以想到进位数量仅为 \(O(m)\) ,设 \(g(i,j)\) 表示考虑了前 \(i\) 位,其中进位为 \(j\) 的方案数。转移的式子看起来很 \(\rm ex\) ,但是思路比较简单,就不写了。时间复杂度是 \(O(m^2\log_2 n)\) 。
Pro Max
在 \(\rm Pro\) 的基础上,修改一下:\(m\leq 10^5, \mathrm{MOD} = 998244353\) 。
考虑每一维的转移线路:
\(n_i\) 表示数字 \(n\) 在二进制下的第 \(i\) 维(从 \(0\) 开始计数),这里没有把转移系数写出来,但可以想到是一个关于 \(k\) 的多项式(实际上就是某个组合数)。这个东西看起来就很像加法卷积,因此可以使用 \(\texttt{NTT}\) 优化。
[ZJOI2010]基站选址
首先想到一个 \(O(n^2k)\) 的 \(\rm dp\) ,设 \(f(i,j)\) 表示考虑了前 \(i\) 个位置,其中强制第 \(i\) 个位置被选择,这时候已经选择了 \(j\) 个位置的最小代价,那么就有:
特别,令 \(D_{n+1} = W_{n+1}=\infty\), 那么答案是:
接下来用线段树维护一下转移最小值,当计算 \(f(i,j)\) 时,令线段树的第 \(x\) 个位置的转移,即 \(f(x,j-1)+w(x,i)\) ,当 \(i\) 变大的时候,有些位置变得没有办法被 \(i\) 覆盖,具体而言,当 \(D_i > D_p+S_p\) 的时候, \(i\) 无法覆盖 \(p\) ,这时候可以用一个单调栈维护当 \(i\) 增大的时候,有哪些变得不能被 \(i\) 覆盖,而对于这些 \(p\) ,当选择某一段 \(x\) 的时候,依然是无法被覆盖的,这个显然可以用二分找出最大,不能覆盖 \(p\) 的 \(x\) ,那么对于 \(1\) 到最大的 \(x\) ,都需要加上 \(W_p\) 。
\(\rm PS:\) 提前将每一个 \(i\) 对应的 \(p\) 和最大 \(x\) 预处理。
[SDOI2016]硬币游戏
考虑经典问题:
有若干种操作,可以用一个编号 \(x\) 和一个集合 \(S\) 描述,可以拿走石子堆 \(x\) 的式子,然后在\(S\) 中的石子堆中加一个石子,满足拿走石子堆的石子堆比任何加入石子的石子堆的编号都靠后。没有办法操作者输。
可以想到,将每一个石子堆中的石子当成一个游戏,设 \(\mathrm{sg}(i)\) 表示一个在编号为 \(i\) 的石子的 \(\rm sg\) 值。那么可以得到计算式:
最终的判定显然是 \(\bigoplus_{i=1}^n [2\not \mid a_i]\mathrm{sg}(i)>0\) 。\(a_i\) 表示初始的时候,第 \(i\) 堆石子的石子个数。
回到这道题,将一个反面硬币翻成正面,实际上可以等于不动原来的硬币,同时增加一个反面硬币,因此可以认为 \(a_i=[\text{第 } i \text{ 个硬币是反面}]\)。
[Code+#1]Yazid 的新生舞会
因为每一个区间 \([l,r]\) 只有至多一个数的出现次数超过 \(\frac{r-l+1}{2}\) ,因此可以考虑每一个数的贡献。
设当前求数 \(a\) 的贡献,设 \(S_i\) 为前 \(i\) 个数中数 \(a\) 的出现次数,那么一个区间 \([l,r]\) 被 \(a\) 贡献,当且仅当满足:
将其移项,可以得到两个结构相同的式子,设 \(f(i)=2S_i-i\) ,那么区间的判定式就变成了 \(f(r)>f(l-1)\) 。这个显然可以用线段树维护每一个 \(f(i)\) 的出现次数,然后考虑每一个点作为右端点。因为每一个数 \(a\) 都需要扫一遍整一个数组,因为时间复杂度为 \(O(na)\) 。
考虑优化,实际上可以优化的点在于两个 \(a\) 之间的空位,这些位置的 \(f(i)\) 显然是一个等差数列。设 \(p_1, p_2(p_1<p_2)\) 表示相邻两个 \(a\) 的位置,然后设 \(c(i)\) 表示 \(p_1\) 之前 \(f(p)=i\) 的 \(p\) 的个数(这个实际上是优化前线段树维护的值),那么区间 \([p_1,p_2)\) 对答案的贡献显然是:
可以发现,之前的线段树求了一个一阶前缀和,而现在要求一个二阶前缀和,这个实际上也可以用线段树维护,而每次往线段树加入的不是一个常数,而是一个等差数列。
CF1446D Frequency Problem
\(\Rightarrow \rm luogu\) 链接(\(\rm Hard Version\))
Easy Version
有一个性质,一定存在一个最优解使得整个序列的众数(设这个众数为 \(B\) )是这个子段的众数之一。
考虑怎么证明,设当前存在一个符合条件的子段(不一定最优),这个子段不包含 \(B\) ,这时可以考虑将其左右扩展,这时候 \(B\) 的数量慢慢增加,因为 \(B\) 是众数,在子段拓展成原序列的过程中,一定存在一个时刻,\(B\) 的数量追上了任何一个非 \(B\) 的数的个数。
接下来考虑每一个数 \(m\) 作为子段的另一个众数对答案的贡献,设 \(h_i=h_{i-1}-[a_i=m]+[a_i=B]\) ,那么就变成了找到最远的两个 \(h_i\) 相同的位置,开个桶即可。
时间复杂度是 \(O(na)\) 。
Hard Version
遇事不决,根号分治。
将所有出现次数大于 \(\sqrt{n}\) 的数按照先前的方式处理。
对于出现次数小于 \(\sqrt{n}\) 的数,这时候 \(B\) 的出现次数也一定不超过 \(\sqrt{n}\) 。
实际上可以可以枚举一个次数限制,这个限制只需要枚举到 \(\sqrt{n}\) 即可,限制所有数字的出现次数不超过限制,一个区间合法需要有至少两个数出现次数恰好到达限制,可以用 \(\texttt{Two pointer}\) 。
CF1613F Tree Coloring
容易想到,因为颜色不能相同,所以不符合条件的父亲和儿子组合会形成若干条不相交的链(一个点也可算链),而每一条链的颜色可以被链头确定,因此可以考虑容斥。
强制连接某些点,设当前形成 \(i\) 条链的方案数为 \(f(i)\) ,那么显然有:
接下来考虑怎么求 \(f(i)\) ,一个点有两个选择:不和儿子合并,和某个儿子合并,不和儿子合并可以让链的数量增加 \(1\) ,而合并儿子则不会增加链的数量,因此可以认为对于第 \(i\) 个点,有多项式 \(d_i+x\) ,其中 \(d_i\) 表示 \(i\) 的儿子的数量,接下来将所有多项式乘起来,这个可以用分治 \(\texttt{FFT}\) 完成, \(f(i)\) 就是结果多项式的第 \(i\) 项。
CF1097G Vladislav and a Great Legend
终于知道 \(k\) 次方和的其中一种计算方式了。
使用第二类斯特林数,根据公式:
当然了,这个公式还有另一个形式:
那么原题的式子就变成了:
稍微变形一下:
后面那个组合数看起来就像是一个背包:首先选择一颗虚树,然后在虚树中选择一些边染色。
设 \(f(u,j)\) 表示在一棵最浅点是 \(u\) 的虚树中,选择了 \(j\) 条边的方案数。接下来可以用合并子树背包的方式向上转移,具体而言,对于子树 \(T_v\) ,合并到 \(T_u\) 时,可以选择边 \((u,v)\) ,也可以不选择 \((u,v)\) ,然后合并上去。同时,为了计算 \(T_u\) 对最后答案的贡献,我们需要记录至少合并了一棵非空子树,然后自己加入虚树,以及至少合并两棵非空子树,但是自己没加入虚树的方案数。
SP11414 COT3 - Combat on a tree
貌似没什么性质,只能用 \(\rm sg\) 函数了,设 \(f(u)\) 表示 \(T_u\) 的 \(\rm sg\) 值,\(g(u,x)\) 表示 \(T_u\) 中删除了路径 \((u,x)\) 之后剩下的森林的 \(f\) 的异或和,那么可以得到(非常恶臭):
首先,为了维护 \(g(u,x)\) 可以使用启发式合并 \(\texttt{Trie}\) ,同时要支持整个 \(\texttt{Trie}\) 异或某一个值,接着还要支持在 \(\texttt{Trie}\) 上计算 \(\operatorname{mex}\) 。