可爱的妹子 II

做题之前,一定要分析性质,起码找到一些结论当突破口。

排除掉没用的东西,尽量剪枝,简化问题。

找规律,打表。;。。。

CF1859D *1800

离散化,设 \(r_i\) 表示 \(i\) 的原值,dp 一个 \(f_i\) 表示在区间 \([r_i,r_{i+1})\) 起始的答案。

容易发现,我们向后跳是一定不优的,设当前在 \(p\),如果要向后跳那么一定是为了之后的向前跳到一个新的位置 \(r>p\),然而我们发现这样的话 \(p\) 也一定包含在 \(r\) 的大区间里面,这样就无需向后跳了。

类似的证明可以发现一定是跳到 \(b_i\) 上,因此从右往左扫,维护当前所有能跳到的 \(b_i\),选取最大的一个用 \(f_{b_i}\) 更新 \(f\),可以用 multiset 实现,时间复杂度 \(O(n\log n)\)

CF1859E *2500

容易想到 dp \(f_{n,k}(k\leq n)\) 表示考虑前 \(n\) 位区间长度和为 \(k\) 时的答案,有转移 \(f_{n,k}=\max_{l\leq k}\{f_{n-l,k-l}+|b_n-a_{n-l+1}|+|b_{n-l+1}-a_n|\}\) 做到 \(O(nk^2)\),过不了。

注意到一个事实:\(|x-y|=\max\{x-y,y-x\}\)。因此 \(|x-y|+|z-w|\) 可以变成四种没有绝对值的式子取 \(\max\),我们随便拎出来一种看看:这时转移是 \(f_{n,k}=\max_{l\leq k}\{f_{n-l,k-l}-a_{n-l+1}+b_{n-l+1}\}+b_n-a_n\),贡献独立出来了,容易优化到 \(O(1)\) 转移,具体地,对每个 \(c\) 维护一个 \(t_c=\max_{n-k=c}\{f_{n,k}-a_{n+1}+b_{n+1}\}\),实际上就是发现矩阵上能转移到 \((i,j)\) 上的点都在 \(y-x=j-i\) 这条斜线上,我们维护的就是每条斜线上的最大值。四个情况下的 \(t_c\)\(\max\) 就能得到答案了。时间复杂度 \(O(nk)\)

[NOIP2022] 建造军营

首先边双内的边随意标记,只有割边的标记情况需要讨论。把边双缩点形成一棵树,边双 \(i\) 中有无军营的方案数是 \(w_{i,0}=(2^{n_i}-1)2^{m_i}\)\(w_{i,1}=2^{m_i}\),起初的想法是令一个 \(f_{u,1/0}\) 表示子树中有无建造军营的方案数,然而发现在转移儿子的 \(f_{v,1}\) 的时候出现了问题:\(f_{v,1}\) 中包含标记的点不通过标记边到 \(v\) 的方案,但这样的方案从 \(v\) 再往外接标记点就已经不合法了,做不到区分 “能通过 \(v\) 继续向外扩展” 和 “到此为止吧” 的答案。

因此考虑把 \(f_{u,1}\) 改成子树中有建造军营且都通过标记边与 \(u\) 连通的方案数,此时容易转移,具体地规定一个顺序扫儿子增量维护,将存在军营的子树分三个情况讨论即可做到线性。时间复杂度 \(O(n+m)\)

CF1827C *2600

朴素的想法会导致算重复。我们考察 beautiful string,可以发现一个 beautiful string 一定有一个唯一的拆分方式:不断地去除它的最短的偶回文后缀。为什么?因为一个偶回文串如果拥有一个偶回文后缀,那么它一定能拆成更短的几个回文串,很显然的。因此考虑不断地加极短回文后缀,令 \(f_i\) 表示以 \(i\) 结尾的 beautiful substring 数量,令 \(g_i\) 表示 \(s_{1,i}\) 最短的回文后缀长度,那么有转移 \(f_i=f_{i-g_i}+1(g_i\neq 0)\)\(f_i=0(g_i=0)\),答案是 \(\sum f_i\)。如果用 manacher 算回文中心长度,单调栈算 \(g_i\) 能做到线性,实际上我写了一个二分哈希和 set 算 \(g_i\)\(O(n\log n)\) 也能过。

[八省联考 2018] 林克卡特树

去掉 \(k\) 条边后变为 \(k+1\) 个连通块,找一条最长带权直径就是在每个联通块里拉一条链出来用 \(v=0\) 的边连接起来,这里方便讨论认为一个点也是链,因此问题转化为找到 \(k+1\) 个不交的链使得链权和最大。显然有朴素的 dp \(f_{u,k,0/1/2}\) 表示以 \(u\) 为根的子树中已选了 \(k\) 条链,\(u\) 不连 / 连一条 / 连两条子树内的边的答案。转移的时候类似树上背包是 \(O(nk)\) 的,无法通过。

感性理解一下答案关于 \(k\) 可能是凸的,因为随着 \(k\) 的增大我们一开始可以取最长的链,接着取次长...这个价值增量会逐渐减小,到了某个阈值之后因为要满足链不交我们又要删去一些边这样。

因此考虑用 wqs 二分降维,转移时增量加儿子,讨论一下是单个连上来,或者是两条子树上的链合起来,不要忘记单个点作为链的情况,顺便统计一下选的链的个数,这里用结构体重载一些东西写起来真的会方便很多。

注意一下 wqs 二分的值域 \(V\) 最后答案里面统的 \(V\times k\) 有没有爆。。我没注意习惯性开了 \(10^{14}\) 然后 \(k=10^5\) 就爆 ll 了。。

时间复杂度 \(O(n\log k)\)

noipd1t3

先转化成留下来的权值和最大,注意到我们删区间有两种目的:分开两个连通块或者在减少一个连通块里面的点数,我们不妨分开想。如果说要使得两个连通块不连通那么必须要删掉经过某个数轴上的缝的所有区间,所以我们 dp 一个 \(f_i\) 表示考虑前 \(i\) 个位置且删掉缝 \((i,i+1)\) 位置的所有区间的答案,答案即 \(f_{V}\),转移即 \(f_i=\max\{f_j+w(j+1,i)\}\),从右往左扫维护 \([j+1,i]\) 里面的前 \(k\) 大的区间权值和,这个可以用一个堆直接做,总时间复杂度 \(O(n^2\log n)\)

[APIO2014] 连珠线

容易发现 fact:蓝边都是一对一对连续匹配起来的,一个点只能是一对蓝边的中点。讨论祖孙和兄弟两种形态一通接边由此容易写出一个 dp 但是是假的。原因在于构造的过程中保持只有一个连通块,兄弟型的蓝边对在某种情况下会寄掉。大概就是一个兄弟蓝边对的两棵子树里面只能有一个有兄弟型的。

然而嗯造这个限制很麻烦,注意到上面的事实也指出了我们可以找一个根使得所有蓝边对都是祖孙形态的,所以只考虑祖孙形态的蓝边对,然后做换根 dp。

dp 一个 \(f_{u,0/1}\) 表示 \(u\) 不是 / 是蓝边对中点的子树内答案,那么转移枚举接不接,\(f_{u,0}=\sum_{v\in S(u)}\max\{f_{v,0},f_{v,1}+w_{u,v}\}\),这里设一个 \(\delta_{v}= \max\{f_{v,0},f_{v,1}+w_{u,v}\}\) 表示 \(v\) 的贡献。\(f_{u,1}\) 就是在 \(f_{u,0}\) 的基础上选择一个儿子撤销它的贡献并加上半个蓝边对,\(f_{u,1}=f_{u,0}+\max\{-\delta_v+f_{v,0}+w_{u,v}\}\)

现在考虑换根,令 \(h_{u,v,0/1}\) 表示从 \(u\) 中剔除儿子 \(v\) 及边 \((u,v)\) 后的 \(f_{u,0/1}\) 值,信息可减,\(h_{u,v,0}=f_{u,0}-\delta_v\) 是容易求的,而对于 \(h_{u,v,1}\) 如果 \(v\) 是被选中作半蓝边对的儿子的话,去除它之后我们还需要再选一个作为蓝边对,维护 \(f_{u,1}\) 的次大值即可。

现在正式维护 \(g_{u,0/1}\) 表示从树中剔除以 \(u\) 为根的子树,\(u\) 不是 / 是蓝边对中点的答案,讨论三种情况,其中两种是接起来一组蓝边对:\(g_{v,0}=\max\{g_{u,0}+h_{u,v,0},g_{u,1}+h_{u,v,0}+w_{u,v},g_{u,0}+h_{u,v,1}+w_{u,v}\}\),你可能会疑惑为什么这里我们使用了在 \(u\) 上的兄弟形态的蓝边对但是注意我们在维护 \(v\) 所以实际上是祖父形态的。\(g_{v,1}=g_{u,0}+h_{u,v,0}+w_{u,v}\)。不需要显式地维护出 \(h\)

时间复杂度 \(O(n)\)

noipd3t2

CF1840F *2200

这不是普及组题嘛?这是 2200?dp 一个 \(f_{i,j,t}\) 表示 \(t\) 时刻能否到达 \((i,j)\),容易发现到达 \((i,j)\) 之前最多被卡 \(r\) 下因此 \(t\) 的量级是 \(O(n+m+r)\) 的。

CF1858D *2200

哎要看数据范围呀

注意到说 \(l_0\) 的贡献会远比 \(l_1\) 大,考虑到数据是允许枚举区间的, \(l_0\) 的贡献占主导地位,我们枚举 \(l_0\) 最终的区间然后算合法的最大 \(l_1\) 即可,直接做 \(O(n^3)\) 的然而预处理一下前后缀答案就平方啦。

CF1845E *2500

感觉有点难,大概是之前没做过这种状态设计。

把每个球标号并设 \(p_i\) 表示球 \(i\) 一开始的位置,注意到最终球的相对位置并不会变,那么对于一个最终局面球的位置 \(t_i\),可以计算出位移和是 \(\sum|t_i-p_i|\),因此可以写出一个 dp \(f_{i,j,k}\) 表示考虑前 \(i\) 个位置,放了 \(j\) 个球,这些球位移和是 \(k\) 的答案,转移的时候枚举当前位置放不放球,\(f_{i,j,k}=f_{i-1,j,k}+f_{i-1,j-1,k-|p_j-i|}\) 能做到 \(O(n^2k)\)

然而继续分析,考虑将 \(j\) 个球移入或移出前 \(i\) 格,那么位移和至少是 \(1+2+\cdots+j=O(j^2)\),进而前 \(i\) 格在最终局面中的球数变化量是 \(O(\sqrt k)\) 级别的,所以总复杂度 \(O(nk^{3/2})\)

反悔贪心,把反悔的决策扔到当前决策集合里面,贪心选择。

CF1852C *2400

把所有 \(k\) 当成 \(0\) 看,就是随时对整个序列 \(\bmod k\),最后要让它们都是 \(0\)。那么每个数被覆盖的次数 \(c_i=a_i+b_ik\),如果知道每个 \(c_i\),那么就是积木大赛,答案是所有正的 \(c_i\) 的差分,直觉感觉一下一个数不会被提升很高,也就是差分不大,实际上最优解一定满足所有 \(c_i\) 的差分在 \((-k,k)\) 之间。证明就是调整一下。

\(d_i=c_i-c_{i-1}\),那么每个 \(d_i\) 有正负两种取值,限制 \(d_i\) 的任意前缀和 \(\geq 0\),取负数没贡献,取正数有正贡献。考虑反悔贪心,从前往后扫,每次先强制选负数,如果导致前缀和 \(<0\) 那么有两种选择:改选正数,或者反悔前面的一个,把它改成正数。每次取贡献最少的一个,开一个堆做即可。时间复杂度 \(O(n\log n)\)

[JSOI2007] 建筑抢修

[ICPC2017 WF] Money for Nothing

容易发现选一对消费商和生产商 \((i,j)\) 的答案是 \((e_i-d_j)(q_i-p_j)\),扔到平面上,其实就是给两个点集 \(A,B\),从 \(A\) 里面选一个做左下角,\(B\) 里面选一个做右上角,组成矩形的面积最大值。

进而能发现如果 \(a_i\)\(a_j\) 的右上角那么 \(a_i\) 是没用的,\(b_i\)\(b_j\) 的右下角那么 \(b_i\) 是没用的。线性扫一遍去掉所有没用的点,(打表发现决策单调性)发现点集的形状是两条斜线,此时证明决策单调性就只需要算一算就行了。分治维护离线转移,\(O(n\log n)\)

[HNOI2003] 消防局的设立 [POI2011] DYN-Dynamite

树上选一些点,每个点有个固定的覆盖半径 \(k\),要求所有关键点得到覆盖,最小化选点数,有一个通用的贪心。

太困了,明天写。

【UER #7】

A

转化成网格图点权的最短路,容易发现只会往下和右面走,而且路径前后两半是对称的,把最外面的设成 \(1\) 层,最里面的是 \(n\) 层,dp 一个 \(f_i\) 表示从第 \(1\) 层走到第 \(i\) 层左上角的最短路径,那么答案就是 \(\min\{2\times f_i+(4(n-1)-1)a_i\}\),就是枚举最里面会走到第几层,然后把两半路径拼起来。

然后发现,我们不会在一个非前缀最小值的层停留超过 \(1\) 次,否则我们把停留的这几步扔到前缀最小值的那一层去走,能减小答案,因此 \(f_i\) 总从它前面的前缀最小值处转移而来,时间复杂度 \(O(n)\)

B

(数据随机的时候,前缀最值变化次数是 \(O(\log n)\) 的。)

牛逼近似算法,我们选一些关键点当答案,就是 \((1+5\%)^n\),容易发现关键点的数量是 \(O(\log_{1+\epsilon}V)\) 的,对于关键点 \(d\),我们双指针求出极差不超过它的最长子序列,设长度为 \(l\),那么所有 \(\mathrm{ans}_i(i\leq l)\) 都跟 \(d\)\(\min\)。最后注意判一下极长相同段对答案置 \(0\)

时间复杂度 \(O(n\log_{1+\epsilon}V)=O(\epsilon^{-1}n\log V)\)

C

\(m\leq 10^3\) 的 Sub,根据鸽巢原理,区间长度大于 \(m\) 的区间必有两个相同的,答案一定是 \(0\)

继续鸽巢,如果一个区间长度是 \(l\),那么其中最小差是不大于 \(\frac{m}{l-1}\) 的。

阈值分治,对于 \(r-l+1\leq S\) 的区间我们暴力区间 dp,复杂度 \(O(nS)\)

其他的区间,扫描线扫右端点,那么扫到 \(a_i\) 的时候就只需要考虑 \(|a_j-a_i|<\frac{m}{S-1}\)\(|a_j-a_i|\) 作为答案的可能,维护一个 \(g_x\) 表示 \(a_1\pm x,a_2\pm x,\cdots,a_r\pm x\) 最后一次出现的位置,那么 \(x\) 能成为答案,就必须保证 \(l>g_{x-1}\)。复杂度 \(O(\frac{nm}{S})\)

\(S=\sqrt m\),时间复杂度 \(O(n\sqrt m)\)

CF1521D *2500

容易用 dp 得到答案,\(f_{u,1/2}\) 表示从 \(u\) 拉下去 \(1/2\) 条链的答案,分类讨论转移,如果图方便就直接给儿子排序吧。

输出方案就比较毒瘤,还需要在 dp 的时候记录选了那两条链,血马麻烦。

有贪心做法,比较容易写

CF1592F1 *2600

容易发现右上角和左下角的操作是 SB,都能换成等价或者更便宜的左上角操作,然后一次右下角操作是可以的,但是如果有两次就可以换成更便宜的左上角操作,因此我们要进行的是若干次左上角操作和一次右下角操作。

现在令矩阵 \(b_{i,j}=[s_{i,j}=\text{B}]\)\(c_{i,j}\) 表示最优解中是否有 \((i,j)\) 的左上角操作,\(d_{i,j}\) 表示 \(c_{i,j}\) 的后缀异或和,从右下往左上扫,这个格子需要被翻转,当且仅当它自己需要被翻转且之前包含它的操作次数为偶数,或者它不需要被翻转且之前包含它的操作次数为奇数,即 \(b_{i,j}\oplus d_{i+1,j}\oplus d_{i,j+1}\oplus d_{i+1,j+1}=1\),那么我们就有了 \(c_{i,j}=b_{i,j}\oplus d_{i+1,j}\oplus d_{i,j+1}\oplus d_{i+1,j+1}\)\(d_{i,j}=c_{i,j}\oplus d_{i+1,j}\oplus d_{i,j+1}\oplus d_{i+1,j+1}=b_{i,j}\),因此得到结论 \(c_{i,j}=b_{i,j}\oplus b_{i+1,j}\oplus b_{i,j+1}\oplus b_{i+1,j+1}\),对这个计数即可。

别的题解得到这个结论的方式也太神仙了我不懂是怎么思考的,只有这个我大概能知道怎么个想法。

最后要处理一次右下角操作,容易发现一次 \((i,j)\) 的右下角操作会翻转 \(c_{i-1,j-1},c_{i-1,m},c_{n,j-1},c_{n,m}\) 于是 check 一下有没有这样的位置即可。时间复杂度 \(O(nm)\)

CF1592F2 *2800

等那个了网络流再来补

[Ynoi2006] spxmcq / 「MCOI-06」Eert Tuc Knil

好吧这里终究是出现了数据结构题

考虑一个 dp 就是 \(f_{u,x}=a_u+x+\sum_{v\in S(u)}\max\{f_{v,x},0\}\) 表示 \(+x\) 的时候子树 \(u\) 的答案,可以发现这棵树里面的边有一些是不存在的,剔除这些边后就有 \(f_{u,x}=a_u+x+\sum_{v\in S(u)}f_{v,x}=\sum_{v\in\mathrm{subtree(u)}}a_v +\mathrm{size}(u)\times x\) 我们从 \(x=-V\) 开始逐渐变大 \(x\),显然所有的边会逐渐逐渐地加进去,我们实时维护这个森林的子树和以及子树 \(\mathrm{size}\),加一条边实际上就相当于一个链加。

那么什么时候 \(u\) 和它的父亲会连起来呢?就是 \(f_{u,x}\geq 0\)\(\sum_{v\in\mathrm{subtree(u)}}a_v+\mathrm{size}(u)\times x\geq 0\)\(x=t_u=\lceil-\frac{\sum_{v\in\mathrm{subtree(u)}}a_v}{\mathrm{size}(u)}\rceil\) 的时候。于是我们从小到大扫 \(x\),并查集维护每个连通块的根,当一个点 \(u\) 满足 \(t_u\geq x\) 的时候开始从底下朝着根加边,在它上面的每个连通块上进行一次链加,并更新这个连通块根的 \(t_u\),直到当前连通块根的 \(t_u< x\),那么停止加边,把这个 \(t_u\) 塞进 set 里面等着下次更新。

容易发现一次修改只会改变 \(O(1)\)\(t_u\),每个点向它的父亲合并的时候才会进行一次链加,那么总共进行 \(O(n)\) 次链加,问 \(O(n+q)\) 次单点值,用树状数组套 DFS 序可以做到 \(O((n+q)\log n)\)

[UNR #6] 机器人表演

判定转 dp:用来计数合法方案数,就是先设计出判定一个算法判定一个方案合不合法,记录这个算法的关键信息,然后再把这个套到 dp 里面去,就是计数判断成这个算法的某个状态的方案有多少个。

先考虑想一个给出 \(T\) 之后判定 \(S\) 插入一些括号之后能不能变成它,用 \(S\) 匹配 \(T\),在插入的括号前缀合法情况下算 \(T_i\) 能匹配到的最大 \(S_j\)。令左右括号是 \(1,-1\),记录期间 \(S\)\(T\) 的前缀和 \(s,t\),设现在匹配到了 \(T_i,S_j\),如果:

  1. \(T_{i+1}=S_{j+1}\),直接贪心地往前匹配。

  2. \(T_{i+1}=(,S_{j+1}=)\),这个时候虽然匹不到 \(S_{j+1}\) 但是插入一个左括号肯定是合法的括号前缀,因此 \(i\leftarrow i+1\)

  3. \(T_{i+1}=),S_{j+1}=(\),先检查此时我们插入的括号前缀是否还有剩余的左括号(即检查 \(t-s>0\) 是否成立),如果有那么插入一个右括号是合法的,\(i\leftarrow i+1\)。否则,我们反悔之前匹配的一段 \(S\),感性上认为这一段 \(S\) 应该是最短的,因此找到最短的 \(j'\) 使得 \(S_{j',j}\) 这一段的和是 \(1\),把它补给接下来这个右括号,\(i\leftarrow i+1,j\leftarrow j'-1\)

最后 check 出来如果都能匹配上并且 \(s=t\) 那么就是合法的。

观察这个算法应该保留什么信息:\(T_i\) 能匹配到的 \(S_j\) 长度,用来检查的 \(t-s\) 即插入的括号前缀还剩几个左括号,那么设 \(f_{i,j,k}\) 表示填了 \(i\) 个数,匹配了到 \(S_j\),还剩 \(k\) 个左括号的方案数。预处理第三种情况里面的 \(j'\),按照上面的方式填下一个 \(T_i\) 转移,复杂度 \(O((n+t)^2n)\)

[ZJOI2016] 小星星

容易想到状压记录子树编号集合,还需要记录子树根的编号来判定能不能连边,那么 \(f_{u,S,d}\) 就能转移了,合并子树的时候要枚举 \(S\) 的子集,复杂度 \(O(3^nn^3)\),无法通过。

正确的想法是考虑放松限制来优化 dp 然后熔池计算答案,注意到如果子树编号比较随便就是可以重复也可以不用一些数那么是容易算的,令 \(f(S)\) 表示是 \(S\) 里面所有数都被用的方案数,\(g(S)\) 表示是用了 \(S\) 里面的数的方案数。有 \(g(S)=\sum_{T\subseteq S}f(T)\),反演得到 \(f(S)=\sum_{T\subseteq S}(-1)^{|S|-|T|}g(T)\),在这里面全集 \(S=\{1,2,3,\cdots,n\}\),只需要令 \(f_{u,d}\) 表示根节点的编号为 \(d\) 的子树 \(g\) 就可以 \(O(n^3)\) 算一项,总复杂度 \(O(2^nn^3)\) 可以通过。

noipd1t4

求一个仙人掌的生成树等价于每个环里面选一条边断掉,那么直接爆搜一下方案能通过 Subtask #1,#2,再去一下重复值可以通过 Subtask #3,#4,下面要分析性质。

我们把所有的可能的 \(\sum a,\sum b\) 扔到平面上,求乘积的最小值,其实就是求一个最小的 \(S\) 使得 \(y=\frac{S}{x}\) 上有标好的点,那么显然只有下凸壳上的点会成为答案。但是点太多了怎么办?考虑合并两个环 \(1,2\) 那么原来的两个点合并成的新点就是,\((\sum a_1+\sum a_2,\sum b_1+\sum b_1)\),是闵可夫斯基和的形式,于是可以直接先把每个环上的凸壳做出来再扔到一起闵可夫斯基和合并,时间复杂度 \(O(n\log n)\)

BZOJ3864 Hero meet devil / [TJOI2018] 游园会

也是判定转 dp 的套路,首先我们有一个经典的 dp 算 \(S,T\)\(\text{LCS}\)\(f_{i,j}=\max\{f_{i-1,j},f_{i,j-1},[S_i=T_i]f_{i-1,j-1}+1\}\),于是直接令 \(g_{i,f}\) 表示填到 \(T_{1,i}\) 的 dp 中那一行的数组为 \(f\) 的串的数量。

然后发现这一行 \(f\) 的差分是 \(0/1\) 那么直接状压 dp 这个差分数组当成 \(f\) 即可。预处理一下差分数组该转移给哪个就行。

时间复杂度 \(O(2^{|S|}m|\Sigma|)\)

游园会就多加一个有么有那几个不行的前缀作为后缀就行了。

[BJWC2018] 最长上升子序列

有一个 \(O(2^nn)\) 的做法可以通过 \(n\) 比较小的点,其他的是巨大牛逼 young 表科技。

还是判定转 dp,对于一个排列我们可以算出来它的 \(\text{LIS}\)\(f_i=\max_{a_j<a_i,j<i}\{f_j\}+1\),然后考虑 \(g_{i,f}\) 表示放了前 \(i\) 个数,前面的 dp 数组是 \(f\) 的答案,然而它肯定爆了,差分也没什么规律,但是注意到 \(f\) 的前缀最大值 \(f'\) 的差分是 \(0/1\),所以可以用它来状压。但是这个时候发现我们一个一个往后填数是有问题的,因为要求是一个排列,我们不知道填没填过,而且加入的数对于前面的大小关系我们是不知道的做不出来 \(f\) 的转移,那么我们不妨直接设 \(g_{i,f}\) 是填了 \(1,2,\cdots,i\) 这些数的答案,往后填 \(i+1\) 的时候枚举填到哪里,此时新填的数一定是最大的,那么有插入的这个位置的差分 \(=1\),前面的差分不变,后面的本来有前缀最大值增大 \(1\) 的地方改成这里增大了,所以后面的差分的第一个 \(1\) 变成 \(0\),其他不变。

看起来是 \(O(n2^n\times n)\) 的但是注意到到 \(g_{i,f}\) 的时候实际上 \(f\) 只有 \(i\) 位有效所以有效状态数是 \(2^1+2^2+\cdots+2^n=O(2^n)\) 的。

[NOI2020] 命运

byd

容易想到 dp,比如 \(f_{u,0/1}\) 表示子树内限制有没有满足完的答案,但是显然不行因为不知道一个限制在哪里结束,所以修整一下,假如从子树里面冒出来一堆没满足的链,那么我们只需要满足最深的那个就行了,所以令 \(f_{u,d}\) 表示子树内没满足的限制里面深度最深的为 \(d\) 的方案数。这里边的深度就是从 \(1\) 开始。

\(g_{u,d}\)\(f_{u}\) 的前缀和,考虑把儿子 \(v\) 合并到 \(u\) 上,\(f_{u,d}\) 怎么办:枚举 \((u,v)\) 染不染色,染了的话 \(v\) 里面随便选,贡献是 \(f_{u,d}\leftarrow f_{u,d}\times g_{v,\text{dep}_v-1}\),不染的话就两边选出一个限制 \(d\),另外一个选比 \(d\) 浅的,贡献是 \(f_{u,d}\leftarrow g_{u,d}\times f_{v,d}+f_{u,d}\times g_{v,d-1}\),所以 \(f_{u,d}\leftarrow f_{u,d}(g_{v,\text{dep}_v-1}+g_{v,d})+g_{u,d-1}\times f_{v,d}\),容易直接 \(O(n^2)\) dp,然后我们离散化这些限制的深度,只有对应的 dp 位置是有值的,可以做到 \(O(nm)\),还有虚树啥的做到 \(O(m^2)\) 我么学过不咋会。

然后看这个式子 \(f_{u,d}\leftarrow f_{u,d}(g_{v,\text{dep}_v-1}+g_{v,d})+g_{u,d-1}\times f_{v,d}\),就是 \(a_i\leftarrow a_i(C+B_i)+A_{i-1}\times b_i\) 尝试线段树合并维护,合并期间要维护 \(a,b\) 前缀和,是一个先乘再加的操作,打标记即可。

做完之后还要给 \(f_u\) 没定义的地方置 \(0\)

时间复杂度 \(O((n+m)\log n)\)

[NOI2022] 移除石子

\(\text{Case 1 : }k=0,l_i=r_i\)

此时即判定一个局面能不能被消掉。我们考虑一下会发现对于 \(2\) 操作:1. 进行的区间互不相同,否则可以换成 \(r-l+1\)\(1\) 操作。2. 区间的长度不会很长,否则可以拆成一些小的区间,具体地,\(3,4,5\) 就可以拼出来所有 \(\geq 3\) 的数,因此 \(2\) 操作进行的区间长度为 \(3,4,5\)

进一步分析性质,3. 以某个位置为起始的区间数量 \(\leq 2\),否则把 \(4,5\) 这两个拆成 \(3,4\) 并在这个位置上进行一次操作 \(1\) 就行。然后这两个区间也不会是 \(4,5\),否则也能拆成 \(3,4\) 和一次操作 \(1\)。所以,以某个位置为起始 / 结尾的区间只可能是 \(\{3\},\{4\},\{5\},\{3,4\},\{3,5\}\)

此时我们可以开始判定了,注意一个新位置只会受到前面几个比较近的 \(2\) 操作影响,再就是考虑前面有哪些区间延长不了了,自然可以想到 \(f_{i,a,b,c,d}\) 表示 \(i-4,i-3,i-2,i-1\) 起始的 \(2\) 操作分别有 \(a,b,c,d\) 个,前缀 \(i\) 能否被消除完。具体地,如果 \(f_{i,a,b,c,d}=1\),我们枚举以 \(i\) 开始的操作 \(2\) 数量 \(j\),然后枚举进一步地发现我们只需要那么由性质 3. \(0\leq a,b,c,d\leq 2\)

妈的不会了,待我理解一下、。。

CSP-S 2022

A

发现数据允许我们做 \(O(n^2)\) 的操作,而且 \(1\) 在答案里面是固定的,所以预处理 \(f_{u}\) 表示 \(1,u\) 同时能走到的点里面的最大的,枚举 \(\text{B,C}\) 然后查 \(f_{B}+B+C+f_{C}\) 即可,因为可能有重的所以维护前三小的即可。

B

分类讨论,ST 表,\(O(n\log n+q)\)

C

发现条件其实只需要就是所有点出度都是 \(1\),但是有改一堆入边的操作,直接做不是很好。

考虑维护一个由所有边的起点组成的可重集 \(S\),那么满足条件就是 \(1~n\) 每个都在 \(S\) 里面出现了恰好一次,我们用 Hash 维护这个东西,给每个点随机一个点权 \(w_u\),那么可重集的哈希就是 \(H(S)=\sum_u\in S w_u\),我们提前维护一个每个点的所有入边的起点的权值和就可以 \(O(1)\) 地做每一个操作了。

时间复杂度 \(O(n+m+q)\)

D

Algorithm 1 : \(k=1\) 的时候,答案即为路径点权和。

Algorithm 2 : \(n\leq 200\) 的时候可以暴力建图跑最短路,最坏是菊花图,\(O(n\times n^2 \log n)\)

Algorithm 3 : \(k=2\) 的时候,选的点只能在 \(s,t\) 的简单路径上,这是显然的。所以把这一条链拆出来 dp,\(O(nq)\)

Algorithm 4 : \(k=3\) 的时候,把这一条链拆出来,那么选的点会是链上的点和离他距离为 \(1\) 的点。因此令 \(f_{u,0/1}\) 表示走到 \(u\) 或者 \(u\) 连出去的一个点的答案,预处理出离某个点距离为 \(1\) 的最小值,dp 即可,\(O(nq)\)

Algorithm 5 : 上面的 dp 要检查很多数,放到矩乘里很拉,所以考虑把 dp 弄简洁一点。

观察性质,可以发现如果选择了一个离链距离为 \(1\) 的点 \(v\),那么上一个点 \(u\) 与他的距离一定是 \(3\),否则可以调整成更好的决策。

再令 \(w_u\) 表示离 \(u\) 距离为 \(1\) 的点权最小值,你可能会说这个可能会和路径里面的点重了呀,但是如果这样的话这个点一定不选的,所以不用管这个了。

\(f_{u,0/1/2}\) 表示最后一个选择到 \(u\) / 离他距离为 \(1\) / 离他距离为 \(2\) 的点的答案,就有 \(f_{u,0}=\min\{f_{u-1,0},f_{u-1,1},f_{u-1,2}\}+v_u\)\(f_{u,1}=\min\{f_{u-1,0},f_{u-1,1}+w_u\}\)\(f_{u,2}=f_{u-1,1}\),写成矩阵就是这个样子:\(\begin{bmatrix}f_{u-1,0}&f_{u-1,1}&f_{u-1,2}\end{bmatrix}\times \begin{bmatrix} v_u&0&+\infty\\ v_u&w_u&0\\ v_u&+\infty&+\infty\\ \end{bmatrix}=\begin{bmatrix}f_{u,0}&f_{u,1}&f_{u,2}\end{bmatrix}\)

DZY loves chinese

对原图随便找一个生成树,对所有非树边随机一个权值,树边的权值是所有经过它的非树边的权值异或和,那么删掉一组边后图不连通仅当这些边权异或线性相关。

noipd4t2

如果每个方案的权值是 \(1\),那么考虑拉一棵生成森林出来,那么剩下边的方案数是 \(2^{m-n+c}\),对于一种非树边的染色方案,对每棵生成树从下开始决定每个边的黑白,唯一对应一种决定黑白的方式,所以总答案 \(2^{m-n+c}\)

对于一个方案它的贡献是其中黑边数的平方,其实就是从在这个方案中的黑边中可重地抽两个的方案数,那么我们可以枚举所有边的有序二元组并算它们属于的方案的数量 \(t\),那么这一对就对答案贡献 \(t\)

这一对边分为三种:有割边,删这两个之后多 \(1\) 个连通块或者删完之后连通块不变。

第一种无解,第二种根据 DZY loves chinese 就是权值相同的边,对应的方案数是 \(2^{(m-2)-n+(c+1)}\),剩下的属于第三种,对应的方案数是 \(2^{(m-2)-n+c}\)。用哈希表数这些边对的数量,时间复杂度 \(O(n)\)

noip20dd2

A

假设 \(b\neq 0\),我们可以从一个四个点的菊花图开始尝试加点到答案的 \(a,b\),初始状态 \(a=3,b=1\) 具体来说,可以通过加一组三度点使得 \(a\rightarrow a+1,b\rightarrow b+1\),可以通过在一个三度点上加一个点使得 \(a\rightarrow a+1,b\rightarrow b-1\),可以在一个度数大于三的点上加点使得 \(a\rightarrow a+1,b\rightarrow b\),第一个不改变 \(a,b\) 的距离,第二个使得距离增加 \(2\),第三个使得距离增加 \(1\),但是前提是用过操作二,所以不难发现 \(a\) 可以无限大,但是与 \(b\) 的距离取值范围是 \([2,3)\cup(3,+\infty)\)

构造就可以按照上面的做法构造。时间复杂度 \(O(n)\)

B

二分答案,然后就相当于 check 能不能只能走 \(d_uw_v\leq t\) 的边走到 \(n\) \((u,v)\)\(d_u\)\(1\)\(u\) 的最短路,时间复杂度 \(O(n\log V)\)

C

先考虑一棵树的情况,此时我们一层一层的从最深的一层开始看,初始所有的边都不选,如果这个节点当前是偶的那么把它到它父亲的边选上,否则就不选,容易发现这样能够保证根以下的节点都是奇的,对于根,注意到总度数和是偶数,那么如果 \(n-1\) 是偶数那么余下的根必然是偶的,否则根必然是奇的。

根据这个过程这个构造方案也是唯一的,于是当 \(n-1\) 是奇数即 \(n\) 是偶数时最大值是 \(n\),直接这么输出答案就可以。

否则由于要求字典序最大,我们需要换一下根,注意到翻转路径 \((u,v)\) 上的所有点就就能只 swap \(u,v\) 的奇偶性,所以现在要找一个点使得翻转根到它之后字典序最大。

直接枚举很难做到好,考虑每个边能不能被翻转,一个边 \(e\) 如果是 \(0\) 那么就想翻转成 \(1\),并且由于它上面的路径都要被翻转,必须要找到它上面第一个编号比它小的边 \(e'\),如果 \(e'\) 也想翻转那么 \(e\) 才能翻转。

所以这个关系能连成一棵树的样子,把它建出来从根开始每次找编号最小的翻转即可。

最后考虑给的图不是一棵树的情况,此时拉一棵生成树出来,把非树边全设成 \(1\),也能按照上面的做法弄出来,所以优先把小边设成非树边,那么这棵生成树就该是最大生成树。

时间复杂度 \(O(m\log m)\)

noip20dd4

A

只需要按照出现位置集合大小从大到小贪心即可。

B

题目要求其实就是找一个点,它的周围一圈全选,其它的最多选 \(k\)个。考虑换根枚举这个点,根固定的情况下求子树 \(f_u\) 表示最多选 \(k\) 个的是好做的,只需给儿子 sort 一遍贪心选即可,然后裤衩 dp \(g_u\) 表示 \(u\) 父亲子树的最多选 \(k\) 个的答案,答案就是 \(\max\{\sum_{v\in S(u)}f_v+g_u+w_{u,v}\}\)

时间复杂度 \(O(n\log n)\)

C

注意到这个实际上就是让我们找一堆矩形,\(a\) 是它们的面积和,\(b\) 是它们的周长和。

那么如果两个矩形有一维相等,那么我们便可以把它们那一维拼起来并分离出来一个宽为 \(1\) 的小矩形,即所有方案都可以变成一堆 \((1,1)\) 和一堆 \((x_i,y_i)\) 其中 \(x_i,y_i\) 全部互不相同,为了方便我们下面的 \(b=\frac{b}{2}\) 即半周长,我们先不考虑 \((1,1)\),因为填上一个 \((1,1)\) 实际上会让 \(a\rightarrow a+1,b\rightarrow b+2\),不改变 \(b-2a\) 的值,那么我们只需要对每个 \(b-2a=k\) 算出一组最小的 \((a,b)\) 就可以容易算出答案了。

下面我们就令 \(f_k\) 表示 \(b-2a=k\) 的最小的 \(b\)

我们按照 \(x\) 从小到大,一组一组地加入 \((x,y)(x<y)\),一次加入 \((x,x+1),(x,x+2),\cdots\),那么可以更新 \(f_k'=\min_y\{f_k,f_{k-(2xy-(x+y))+x+y}\}\),暴力做会变成 \(O(n^3)\) 的,但是我们把 \(f_{k-(2xy-(x+y))}+x+y\) 整理一下变成 \(f_{(1-2x)y+x+k}+x+y\),下标处就是一个关于 \(y\) 的一次函数,这些一次函数的斜率都一样,就是偏移了一点,那么我们先花 \(O(n)\) 把每个一次函数对应的 \(\min\{f+y\}\) 记录下来,然后再 \(O(n)\) 偏移一下更新 \(f_k\) 即可。现在时间复杂度是 \(O(n^2)\) 的。

注意到所有矩形的每一维互不相同,并且有钦定 \(x<y\),那么我们外层的 \(x\) 就只需要枚举到 \(O(\sqrt n)\)。时间复杂度 \(O(n\sqrt n)\)

为什么被卡常了。

D

首先需要搓出来合法序列的充要条件:每个数右边比它小的数的数量为偶数。设这个值为 \(r_i\),我们尝试维护它。

我们只维护 \(r_i\) 的奇偶性,操作是交换两个数 \(a_l,a_r(l<r)\),那么会让 \([l+1,r-1]\) 中值域在 \([a_l+1,a_r-1]\) 中的数的 \(r_i\) 取反,\(r_l\)\(r_r\) 则是加上区间 \([l+1,r-1]\) 中比他们小的数的贡献。

询问即找到最右边的 \(r_i=1\) 的位置,答案就是 \(i+1\)

要求维护 \(a_i\) 和对应的 \(r_i\),支持单点改 \(a_i\) 取反对应 \(r_i\),区间对其中 \(a_i\) 在一个区间内的 \(r_i\) 取反,区间查比一个数小的 \(a_i\) 数量,全局查最右边的 \(r_i=1\) 的位置。直接考虑分块,块内维护 sort 的 \(a_i\)\(r_i\) 的差分,操作一可以直接下放差分之后重构块,操作二对散块重构它的 \(r_i\),整块可以在 sort 的 \(a_i\) 上 lower_bound 出来要修改的 \(r_i\) 区间然后直接在差分上修改,操作三也是散块暴力查整块 lower_bound,操作四就对每个块存差分中 \(1\) 的数量,从右往左扫到第一个有 \(1\) 差分的块,然后再在块内暴力找即可。

操作一重构注意不需要重新排序而是直接插入,花 \(O(B)\),操作二的重构因为不改 \(a_i\) 就不需要再排序了,花 \(O(B+\frac{n}{B}\log B)\),取 \(B=O(\sqrt{n\log n})\) 得到一个 \(O(q\sqrt{n\log n})\) 的做法,可以通过。

不精细实现写傻逼的 \(O(n\sqrt n\log n)\) 也是可以过的。

某道noipd4t3

首先考虑 \(a_i\) 是排列的时候,直接想有点难,我们就考虑最大的元素 \(n\),当 \(b_i=n\) 时意味着此时堆恰好是空的,因为没有数比它大能继续留在堆里了,\(a_1,a_2,\cdots,a_i\) 就一定分给 \(b\) 的前 \(i\) 个,而 \(a_{i+1},a_{i+2},\cdots\) 就要分给后面的,那么之后的操作就和前面这部分独立了,这就启发我们按照最值分治,即如果钦定 \(b_i\) 是最值,那么答案就是 \(a_1,a_2,\cdots,a_i\) 中去掉 \(n\) 的答案乘上 \(a_{i+1},a_{i+2},\cdots\) 的答案。

由于我们不断地删去最大值,要求的子序列一定是只包含 \(\leq\) 某个数的子序列,所以令 \(f_{l,r,x}\) 表示只保留 \([l,r]\)\(\leq x\) 的数组成的子序列的答案,那么枚举最值 \(x\),假设在 \([l,r]\)\(x\) 的位置为 \(p\),那么 \(f_{l,r,x}=\sum_{i=p}^r f_{l,i,x-1}\times f_{i+1,r,x}\),如果 \(x\) 不在 \([l,r]\) 中,那么 \(f_{l,r,x}=f_{l,r,x-1}\)

如果元素有重复的,那么我们考虑按照出现的前后给它们编号,并且指定编号小的在堆中会先出,那么就可以变成排列了。

时间复杂度 \(O(n^4)\)

posted @ 2023-08-22 13:51  yukari1735  阅读(67)  评论(2编辑  收藏  举报