9月记录
282.CF2001
D
贪心做不明白了。
按照字典序贪心。
比如说奇数位,让颜色最大。
有一种说法是选择一个最大的颜色填入,使得填入后剩余颜色都可填入。
形式些表述,我们已经构造了 \(b_1,b_2,\cdots,b_j\),其中 \(b_j=a_i\),设 \(l_x\) 是颜色 \(x\) 出现在 \(a[i+1,n]\) 的最后一个位置,那么我们可以选择 \(a[i + 1,\min_{1\le x\le n}(l_x)]\) 中的任何位置,找到里面的最小/最大颜色,更新即可,可以用线段树。
E1
记 \(g_{i,j},h_{i,j}\) 分别表示深度为 \(i\) 的大根堆,使用了 \(j\) 次操作,可以进行一次 pop
的数量,以及深度为 \(i\) 的大根堆,使用了 \(j\) 次操作,的数量。
转移简单,可以用前缀和优化。
E2
可以使用两次 pop
了,需要记录每个点最大儿子的这个信息。
记 \(f_{i,j,k}\) 表示深度为 \(i\) 的大根堆,使用 \(j\) 次操作,最大儿子为 \(k\),可以进行两次 pop
的方案数。
记 \(g_{i,j,k}\) 表示深度为 \(i\) 的大根堆,使用 \(j\) 次操作,最大儿子为 \(k\),可以进行一次 pop
的方案数。
\(h_{i,j}\) 同理。
转移考虑 \(f\),的两次 pop
,可以两次都在同一个子树,也可以两次在不同子树,讨论一下即可。
前缀和优化,\(\mathcal O(nk^2)\)。
283.[ABC367G] Sum of (XOR^K or 0)
考虑每种异或和的方案数。
则
其中 \(x\) 作异或卷积,\(y\) 作循环卷积。
考虑 FWT
,记 \(x\oplus y=\operatorname{popcnt}(x\and y)\bmod 2\)
那么 \(A'\) 中的每个位置只能是 \(1+y\) 或 \(1-y\),即 \((1+y)^a(1-y)^b\)。
其中我们知道 \(a+b=n\),考虑求出 \(a-b\),得到 \(a,b\)。
然后我们只需要知道 \(a,b\) 下式子 \(y^0\) 的系数,因为 IFWT
做的是线性变换,所以次方不会改变。
根据定义,有 \(A=\sum [A_i\oplus w=0],b=\sum[A_i\oplus w =1]\)。
那么将 \(A_i\) 扔到一个桶中,做 FWT
就能得到每一位上 \(a-b\) 的值了。
时间复杂度 \(\mathcal O(nm+mV+V\log V)\)。
284.各种多项式操作的 n^2 递推
285.[ABC366G] XOR Neighbors
考虑高斯消元。
如果存在自由元,那么就是无穷解。
要保证自由元 \(\ne 0\),就给每个自由元赋值 \(2^i\)。
286.[ABC363G] Dynamic Scheduling
https://www.luogu.com.cn/article/o1mle23w
这里讲得挺好。
模拟费用流+线段树分治(去掉删除操作)
线段树维护流量,增量考虑增广路以及正环的影响。
287.CF2004G
容易发现,奇数段不超过 \(1\)。
就可以 dp
了,记 \(f_{i,j}\) 表示前 \(i\) 个数最后一段以数字 \(j\) 为开头。
用矩阵乘法优化一下。
然后每 \(k\) 个分一块,维护块中前缀后缀积,就能一次矩阵乘法回答询问。
288.CF1978F
考虑一条斜线一定联通,两条斜线之间有连边只需要看最短距离。
就能变成一个一维问题了。
枚举 \(\gcd\) 的因子即可,找出 \(\mathcal O(n\ln n)\) 个数,相邻距离 \(\le k\) 的连边即可。
289.CF1979E
曼哈顿距离等边三角形的边长一定是偶数。(可能有用的性质)
旋转坐标系,变成切比雪夫距离,此时一定有:
在 set
里面判断就好了。
hot!!!
290.好串 (good)
考虑先处理前缀,所有前缀 \(\min\) 的位置前面都加个数,然后前缀 \(\min\) 都被摊平在 \(x\) 轴上,只需要记录后缀的前缀最小值个数,就能得到一个数被摊平后的权值,找到最大的与右端点的距离即可。
可以扫描线单调栈维护。
291.子串 (substring)
建出 sam
,然后就是经典分治 ntt
合并重链了。
292.CF1366G
考虑每个点的策略:
-
匹配,要求是字符;
-
手动删除,无要求;
-
与后面的
.
匹配,要求是字符,且中间操作后无剩下字符。
考虑朴素 dp
,发现如果一个字符无法匹配,但他被后面的 .
删除了,这种情况无法计算。
建出括号树,如果在一个子树内剩下至少一个字符,那么必须是包含根的一个联通块,且最优情况是这个联通块的点的右括号都手动删除了,某些不选的字符显然保留右括号最优,否则的话,匹配他的右括号右移(又多个要求一部分全部删完的限制),不优。
我们可以不建出括号树来,上面的发现告诉我们什么,可以在朴素 dp
的基础上加上“跳子树”的操作,发现这样最优解一定被考虑到了。
时间复杂度 \(\mathcal O(n^2)\)。
293.CF865C
类似题
https://pjudge.ac/contest/1114/problem/21743
https://www.luogu.com.cn/problem/AT_arc016_4
设已经结束第 \(i\) 关,这一次用时为 \(j\),后面的期望用时为 \(dp_{i,j}\)。
简单来看设 \(dp_{0,0}=x\),则每个 \(dp\) 值都可以表示成关于 \(x\) 的一次函数,且导数在 \([0,1]\),那么 \(dp_{0,0}-x\) 的导数在 \([-1,0]\)。
我们要求的是 \(dp_{0,0}-x=0\) 的解,已经知道 \(dp_{0,0}-x\) 单调递减,那么二分即可。
294.P6622 [省选联考 2020 A/B 卷] 信号传递
考虑状压当前选了哪些点,将贡献拆到点上,可以预处理出 \(g(s,i)\) 表示 \(s\) 集合在 \(i\) 前面,对 \(i\) 的贡献系数。
时间复杂度 \(\mathcal O(m2^m)\)。
空间优化就折半就好了。
295.CF1188D
显然一个数不会加同一个数大于一次。
则构造序列 \(b_i\ge 0\),使得 \(\forall i\in[1,n],a_i+b_i=a_n+b_n\),且 \(\sum_{i=1}^{n}\operatorname{popcnt}(b_i)\) 最小。
知道 \(b_n\) 即可,转化为 \(\sum_{i=1}^{n}\operatorname{b_n+a_n-a_i}\) 最小。
考虑从低位往高位 dp
。
每次需要知道一位进位后有多少个 \(1\)。
发现只需要知道:
- 每个数这一位是什么值;
- \(x\) 这一位是什么值;
- 哪些数被上一位进位了;
由于每个数加的数相同(是 \(x\)),那么第 \(j\) 位被进位的数,显然是前 \(j-1\) 位的数 \(val+x\ge 2^j\),则 \(val\) 就是按照前 \(j-1\) 位从大到小排序后的前缀。
记 \(f_{i,j}\) 表示考虑到了第 \(i\) 位,被第 \(i-1\) 位进位了 \(j\) 个数,那么我们执行一次排序就能知道是哪些数被进位了,后面就好办了。
296.P10430
将操作倒过来,每次可以单点减 \(D\),要求最后单调不增(如果从加法角度看的话,会有很多限制)。
从后往前贪心,如果 \(a_i>a_{i+1}\),就修改 \(a_i\),那么最后一定有 \(a_i>a_{i+1}-D\)。
可以发现 \(a_i\) 和 \(a_{i+1}\) 在之后一定是要么都不变,要么都修改,类似连续段合并。
按照右端点扫描线,维护要连续段,加入单点,暴力合并连续段,修改查询用线段树维护即可。
时间复杂度 \(\mathcal O(n\log n)\)。
297.CF1981
hot!!!
298.CF1957
299.CF1981F
设 \(f_{u,j}\) 表示 \(u\) 子树,包含 \(u\) 的链不含 \(j\) 的答案,则钦定这条链按照 \(\operatorname{mex}=j\) 计算答案。
发现最优解一定会被 \(\operatorname{mex}\) 符合的状态考虑到,且不符合的一定不优。
分类讨论合并即可。
一种优化是 \(\operatorname{mex}\) 的大小不会很大。
用线段树合并还能优化到 \(\mathcal O(n\log n)\)。
区间加,区间取 \(\min\),区间最小值,完全不用吉司机。
300.CF771E
hot!!!
怎么300了。
考虑 dp
,\(f_{i,j}\) 表示第一行取到 \(i\) 列,第二行取到 \(j\) 列。
要么不取,转移到 \(i+1\) 或 \(j+1\),要么取最小的右端点,往后转移。
考虑每种方案定义选择顺序,每次选取左端点最小的段,即对于 \(f_{i,j},i\ne j\),如果要转移,选择左端点最小的转移。
观察到当 \(i=j\) 时转移才有交叉,考虑记录 \(f_{i,i}\)。
简要证明若 \(f_{i,j},i<j\) 且 \(f_{i,j}>f_{i,i}+1\),要么不合法,要么可以有 \(f_{q,q}\) 转移得到。
则对于每个 \(f_{i,i}\),只需要保留 \(f_{i,j}=f_{i,i}+1\) 的状态,另一行同理,显然 \(j\) 越小越好。
总共 \(\mathcal O(n)\) 个状态,每个状态 \(\mathcal O(1)\) 的转移,所以是 \(\mathcal O(n)\) 的。
301.CF1821F
很神!
https://www.cnblogs.com/Zeardoe/p/17003282.html
302.QOJ8141
很神的题,dp
状态想不到,太暴力了。
记 \(f_{l,r,k,d}\) 表示区间 \([l,r]\),然后 \([l,l+k]\) 是最左边的段,这个段的和剩下长度为 \(d\) 的前缀,其他都是回文的,这样相当于实际钦定了回文中心在中间,后缀同理,可以转移。
随便跑跑就行了,鉴于这题几乎没人写,所以就不写了。
303.mx1
A
操作相当于 *2,+1
并且操作三不会影响最后两个数,所以倒着搞就行了。
B
直接容斥。
有一个正常的 \(nk^3\) 的 dp
。
抽象问题,转换维度,可以优化成 \(n^2k^2\),不过还有 \(n^2\ln n\) 的做法,在下面。
哈哈,超级快速的多项式直接草过去了。
C
如果在笛卡尔树上考虑的话,每个节点肯定选择最长的最优,所以有用的只有 \(\mathcal O(n)\) 个区间。
每个区间肯定是从不合法到合法,单点修改就在笛卡尔树的祖先上考虑,倍增维护一个点的最浅的不合法祖先,每次修改的时候判断其是否变成合法了即可。
用树状数组实时维护合法区间的长度,回答询问即可。
D
就是cf的某道题
304.QOJ9254
加强版在这。
考虑我们容斥后需要求什么,有 \(n\) 个互不相同的球,有 \(m\) 个互不相同的箱子,每个箱子的球数 \(\le k\) 的方案数。
记 \(f_{i,j}\),则转移为
容易发现第二维减一,第一位就会减 \(k\),所以第二维是 \(\mathcal O(\frac{n}{k})\) 的,时间复杂度为 \(\mathcal O(\frac{n^2}{k})\)。
总的复杂度就是 \(\mathcal O(n^2\ln n)\)。
305.P9701 [GDCPC2023] Classic Problem
找出所有关键点,那么一个极长区间,满足区间内没有关键点,一定存在一个方案满足最小生成树上这个区间的点构成一条链。
所以可以缩成 \(\mathcal O(m)\) 个点。
模拟 B
算法,需要支持找出每个点连到其他联通块的点的最短边。
先考虑掉特殊边,容易。
再考虑普通边,在值域上考虑,两个点没有特殊边,那么最短的普通边就是左右端点距离的最小值。
维护 \(pre_i,nxt_i\) 表示 \(i\) 左边第一个与 \(i\) 不在同一联通块的点,后者同理。
但是中间可能会跳到一个点 \(nw\),\((nw,i)\) 有特殊边,所以就不存在普通边,以向左条为例,这时 \(nw--\)。
如果 \(nw\) 减到一个与 \(i\) 同颜色的点,就跳 \(pre\) 边。
可以证明时间复杂度 \(\mathcal O(m)\),总时间复杂度 \(\mathcal O(m\log m)\)。
306.QOJ7520
如果只有一天,就是个经典??的贪心问题。
对于 \(a_i\le b_i\) 的怪物,按照 \(a_i\) 从小到大打。
对于 \(a_i>b_i\) 的怪物,反过来考虑,即 \(-b_i,+a_i\),就是第一类问题了,这部分按照 \(b_i\) 从大到小打。
考虑排序得到最优打怪顺序,有 \(\mathcal O(n^2)\) 个时间段的打怪顺序是不同的,计算 \(x<y\) 变到 \(x>y\) 的时刻。
每个时间段的最优打怪顺序的相同的,最优答案是一次函数的半平面交,转成凸包,计算贡献即可,时间复杂度 \(\mathcal O(n^3\log n)\)。
307.P10198 [USACO24FEB] Infinite Adventure P
首先有一个倍增,记 \(f_{i,k,j}\) 表示从点 \(i\) 开始,走 \(2^k\) 步,初始时间模意义下为 \(j\)。
但是 \(t_v>t_u\) 的话,信息不够,无法合并。
修改定义,记 \(f_{i,k,j}\) 表示从点 \(i\) 开始,走 \(2^k\) 步,钦定如果走到一个点 \(t_v>t_u\) 就停止,初始时间模意义下为 \(j\),走到的点。
同时记 \(g_{i,k,j}\) 表示从点 \(i\) 开始,走 \(2^k\) 步,钦定如果走到一个点 \(t_v>t_u\) 就停止,初始时间模意义下为 \(j\),到停下来时走了多少步,走不到就是正无穷。
这样可以合并,两个 \(\log\) 回答询问,因为每跳一层,在一层走的复杂度是 \(\log\)。
但是预处理是三个 \(\log\) 的,每种状态都会下降,就要 \(\log^2\)。
考虑修改定义,记 \(f_{i,k,j}\) 表示从点 \(i\) 开始,钦定走了 \(2^k\) 个 \(t_v=t_i\) 的位置,如果走到一个点 \(t_v>t_u\) 就停止,初始时间模意义下为 \(j\),走到的点。
记 \(g_{i,k,j}\) 表示从点 \(i\) 开始,钦定走了 \(2^k\) 个 \(t_v=t_i\) 的位置,如果走到一个点 \(t_v>t_u\) 就停止,初始时间模意义下为 \(j\),到停下来时走了多少步,走不到就是正无穷。
这样按照 \(t_u\) 从小到大预处理,合并的时候就不会下降了,是一只 \(\log\) 的,修改是两只 \(\log\) 的。
每次跳的时候,如果不是路径 \(t\) 的最大值,直接跳到 \(t_v>t_u\) 的位置,否则倍增,这样跳一次 \(\log n+\log V\)。
最多下降 \(\log n\) 次,所以查询时 \(\log n(\log n+\log V)\) 的。
308.平方问题
发现 \(998244353\) 是 ntt
模数,\(2^k\equiv 1\bmod (p-1)\) 的循环节很小,是一个 \(\varphi\) 形的循环节。
线段树维护两类数,一类是还没进入循环的数的和,另一类是已经进入的了。
修改,如果一个区间有还没进入循环的数,暴力递归修改。
一个区间维护 \(sum_j\) 表示区间第二类数在环上跳 \(j\) 步的和,可以合并。
309.取石子
大型找规律题。
310.匹配
好神奇。
某两个部分有大小为 \(?\) 的匹配只需要考虑度数和,因为还顶了一个上界。
找到这样一个结构,就能证明最大匹配是 \(x\)。
附证明:
dp
就行了,注意维护非 \(0\) 度点。
311.移球游戏(ball)
给每个球按照颜色排序重新附上一个排列的颜色。
如果我们能将球按照颜色排序,列排序,同一列从大到小排序,构造就从后往前将一列取出即可。(nm没想到,我是sb
有两种写法。
考虑冒泡排序,考虑相邻两列,存在要交换的颜色,先从标号为 \(m\) 个 \(0\),\(m\) 个 \(1\),然后将垃圾桶拉来,进行分类即可。
然后还需要将一列排序,同样将垃圾桶拉来,基数排序。
另一种写法是我的sb写法。
考虑分治,左边选择一列,右边选择一列,一定有 \(0\) 个数 \(\ge m\) 或者 \(1\) 个数 \(\ge m\)。
根据这个选择凑 \(0\) 还是凑 \(1\),操作两列时,将两列交换到中间位置,配合垃圾桶操作。
交换满的两列,同样考虑将垃圾桶拉来进行交换。
写的常数很大。
312.哈密顿(hamilton)
考虑将哈密顿路径拆成两个部分,\(1\to u\),\(1\to v\)。
记 \(f_{s}\) 表示从 \(1\) 出发,经过了 \(s\) 的点,可以成为终点的点有哪些。
推一下可以计算。
枚举集合 \(s\),枚举终点,取补集的并即可。
313.CF1483F
枚举 \(s_j\),找到最长的后缀满足是给出的串,集合 \(S\)。
显然 \(s_i\) 只能在 \(S\) 里选,还有一个条件是对于 \(s_i\) 每次出现的位置,不能有串包含它。
考虑串包含它的情况,要么它不是这个前缀的最大后缀,要么是,但是被一个 \(S\) 里的串包含。
反过来就是它是前缀的最大后缀,且不能有 \(S\) 里的串包含它。
惊奇地发现这样就可以考虑了,计算一个本质不同的串(\(S\) 里)的被 \(S\) 的串包含的次数,如果这个次数等于他的出现次数,就是有解的。
时间复杂度 \(\mathcal O(|S|\log|S|)\)。
314.吃串串(string)
同样考虑 \(s_k\),\(s_i\) 只能在每个前缀的前两大后缀里取,记为集合 \(S\)。
对于 \(S\) 里的一个字符串,显然它不能是一个后缀前 \(3\) 大以上的点。
且 \(S\) 中的串需且仅需(只能)有一个包含它。(这么牛,因为一个后缀如果第三大包含它,前两大一定被计算了,否掉这个串了)。
时间复杂度 \(\mathcal O(|S|\log|S|)\)。
315.AT_awtf2024_a Moving Slimes
可能有点懂了。
显然选择一段前缀和一段后缀最优。
类似物理分析,考虑选择的前缀的重心和后缀的重心,这样前缀后缀内部的吸引就可以不用考虑了。
可以发现前缀后缀在没有合并时,相对速度始终为 \(k\),否则严格更小,时间记为 \(A_i\)。
考虑答案下界,即考虑合并对速度无影响,那么答案至少了为 \(\max(A_i)\)。
考虑答案上界,对于最后一个合并的相邻位置 \(p,p+1\),则 \(A_p\) 表示的就是最后时间,所以答案至多是 \(\max(A_i)\)。
于是一种方案就是 \(\max(A_i)\)。
考虑 \(k<n\),对于前缀选 \(i\) 个,后缀选 \(k-i\) 个,如果以 \([i,k-i]\) 为空隙不是这种方案 \(A_i\) 的最大值,那么一种用另一个 \(i1\),这种空隙比他大。
316.QOJ7742
一个很惊奇的发现。
找到一个点 \(u\),一直匹配 \(t\) 的前缀,第一次跳 fail
跳到的点 \(t\),匹配了 \(j'\) 次跳到的。
如果 \(dep_t\ge t\),那么根据 fail
的定义,后面的答案(\(j\ge j'\))等价于 \(t\) 的 \(j'\) 级祖先的 \(j\ge j'\) 的答案。
否则,后面的答案等价于从根出发的一个后缀的答案。
如果是第一种情况,\(u\) 和 \(t\) 的 \(j'\) 级祖先只有一段前缀有差别,且差别是一段定值。
如果是第二种情况,就需要提前加上前 \(j'\) 次的贡献,需要前缀加等差数列。然后加上从根出发的贡献,再扣掉从根出发的前 \(j'\) 次的贡献。
维护一个 \(val_u\) 表示点 \(u\) 的所有 \(f\) 需要带上 \(val_u\) 的系数贡献到答案,发现这样就很好维护答案的二阶差分。
从而离线递推出答案。
时间复杂度 \(\mathcal O(n\log n)\)。
317.AT_abc370_g
记 \(f(n)\) 表示长度为 \(m\) 的正整数序列,乘积为 \(n\) 的方案数,发现对每个质数插板即可,这个东西是积性的。
将好数的条件拆到质因子上,发现一个数不是好数这个东西是积性的,于是考虑容斥。
两个积性函数的点积也是积性的。
这两个函数的质数处以及次方处取值容易计算,且将质数拆开构造完全积性函数的前缀和,涉及到计算前缀 \(\bmod 3=r\) 的质数个数。
考虑到 min-25
算 \(G(m)=\sum_{i=1}^{m}[i\in pr] f(i)\) 时,实际上无需用到 \(f\) 是积性函数这个性质,只要能快速求构造出来的完全积性函数前缀和即可,所以也是容易计算的。
318.想要有钱(money)
一种思路是考虑倒序将数位移到第一位。
这样 n...1
就可以卡了。
一种优化是,找到 \([1,\frac{n}{2}]\) 中 \(>\frac{n}{2}\) 的数,和 \([\frac{n}{2}+1,n]\) 中 \(\le \frac{n}{2}\) 的数,设有 \(c\) 个,操作 \(c\) 次,前一半就没有大于一半的数了,花费 \(\frac{1}{2}\),那么位移大于一半的数时,代价就会很小,位移小于一半的数时,前缀已经填满了,那么代价也会很小。
另一种优化是将当前数往右移动,设 \(j\to pos\),只需要 \([j+1,pos-1]\) 没有数选即可,找到所有选上没有影响的位置选上,暴力找到最优移动点。
319.想要大的(big)
太shi了,不过想清楚了还是很好写的。
首先 \(r\leftarrow r-n+1\),就不需要考虑边界了。
考虑拆到线段树的若干区间上,满足 \([l,l+2^k-1]\) 的区间,答案只有 $\log $ 个。
就做完了,比较难写。
320.想出去玩(travel)
怎么被这种题秒了啊,实在想不到。
考虑边分治,跨过这两棵子树的边共 \(3\) 条,从这 \(3\) 条边开始跑最短路。那么之后的答案就可以不考虑经过这 \(3\) 条边的,递归到子树做就可以了。
复杂度\(\mathcal O(n \log^2 n + q \log n)\)。
注意边分治的二度操作。
321.mx2
这整场都太hot了!!!
hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!hot!!!
A
考虑到右边其实是冒泡排序的复杂度,左边是冒泡时每个数移动方向固定的复杂度,即左边是冒泡的下界。
考虑到 3 2 1
,\(2\) 方向不固定,于是可得答案最长下降子序列 \(\le 2\),可以发现这样一定满足。
怎么求呢,玩一下又知道,每次填的数要么扩展最大值,要么填上 \(\operatorname{mex}\),设 \(f_{i,j}\) 表示前 \(i\) 个数,最大值为 \(j\) 的方案数。
发现 \(f_{i,j}\to f_{i+1,k+1}\) 或者 \(f_{i,j}\to f_{i+1,j+1}\),这个东西无需考虑后者的选择,因为天然满足 \(i\le j\),当 \(i=j\) 是才不能填 \(\operatorname{mex}\),而我转移中已经钦定 \(i\le j\)。
在网格图上考虑,每次可以向上若干步再向右一步,或者直接向右一步,不越过 \(y=x\)。
奇妙的分析,发现前者只是(每次可以向上走一步,或者向右走一步)的所有路线扩展,所以其本质和 \(C(n+m,n)\) 是一样的,反射容斥即可。
B
你说的对,但是被薄纱。
被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱被薄纱
考虑求出 dag
的拓扑序。
对于一条边 \((u,v)\),当删除的点在 \([p_u+1,p_v-1]\) 时,经过 \((u,v)\) 的最长路径存在,即 \(f_u+g_v+1\)。
对于一个点 \(u\),当删除的点在 \([p_u+1,n]\) 时,路径 \(f_u\) 存在,当删除的点在 \([1,p_u-1]\) 时,路径 \(g_u\) 存在。
但是,这显然是必要条件,但是怎么证明充分呢,即怎么证明用每个时刻用这些存在的路径的 \(\max\) 一定有最长路呢。
考虑拿出任意一条最长路,删除的点一定是这条路上的某个点。
考虑任意一条路径,将路径上的点的拓扑序取出,当删除的点在相邻两点之间时,这条路径就会有贡献,点的贡献是特殊的。
C
假设确定了点 \(p\) 的第 \(p_1,\cdots,p_{i-1}\) 维,当前星星加入后不合法,考虑用星星的第 \(p_i\) 维确定 \(p\) 的第 \(p_i\) 维。
枚举 \(k\) 的每个排列,一定能算到最优解,时间复杂度 \(\mathcal O(n^2k!)\)。mdmdmdmdmdmdmd 这都想不到。
怎么想到,找到一个贪心过程,探寻经过贪心过程得到的最优解的某些妙妙性质。
考虑对每个最优解如果某维是不必要的,设为 \(-1\),否则找到这一位最早的必要位置,标记。
如果一个位置没被标记,显然前面标记点对应的维度已经满足他的条件了。
考虑将维度按照最早的必要位置排序,得到一个维度的排列,按照这个顺序贪心。
显然存在一组最优解(调整),满足前缀的标记点不被之前已经填入的维度满足,即在这个位置填数是必要的。
发现这样就能用一种排列,描述一种可能的最优解了。
考虑 dp
优化这个贪心,从第 \(i\) 颗星星开始用排列 \(p\) 进行匹配,定义 \(f_{i,p,j}\) 表示点 \(P\) 的第 \(p_j\) 维第一次发生失配的位置失配位置同时表示第 \(p_{ j+1}\) 维第一次进行匹配的位置)。那么使用 \(p\) 匹配,以 \(i\) 为左端点最长的合法子段为 \([i, f_{i,p,k}-1]\)。
考虑从后往前转移。
如果 \(f_{i+1,p}\) 中 \(p_1\) 满足星星 \(i\) 和 \(i+1\) 的第 \(p_1\) 维相同,那无需对 \(p\) 做任何调整。
否则我们要在 \(p\) 的基础上找到另一个排列 \(q\),让 \(f_{i+1,q}\) 转移到 \(f_{i,p}\)。
注意到我们一定会将点 \(P\) 的第 \(p_1\) 维确定为第 \(i\) 个星星的第 \(p_1\) 维。不妨将 \(p\) 记作 \([p_1]AB\),那么 \(q\) 就是 \(A[p_1]B\)(\(B\) 可以为空)。\(q\) 到 \(p\) 的变化相当于提前使用第 \(p_1\) 维进行匹配,如果 \(q\) 中第一次使用第 \(p_1\) 维的星星和星星 \(i\) 的第 \(p_1\) 维相同就可以把 \(q\) 中的 \(p_1\) 提前成为 \(p\),并且只能从这些状态转移。
那么枚举所有的 \(q\),\(p_1\) 越靠前一定越优。时间复杂度 \(O(nk!)\)。
这个实现方式太妙了。
考虑在 trie
上完成匹配。
void dfs(int now, int lst, int c, bool have) {
// i已经匹配,i+1已经匹配,维度,p[1] 已经出现了
if (have) {
newdp[now] = lstdp[lst];
for (int i = 1; i <= k; i++)
if (son[now][i])
dfs(son[now][i], son[lst][i], c, 1);
} else {
if (a[lstdp[lst] + 1][c] == need)
dfs(now, son[lst][c], c, 1);
else {
newdp[now] = lstdp[lst];
for (int i = 1; i <= k; i++)
if (i != c && son[now][i])
dfs(son[now][i], son[lst][i], c, 0);
}
}
}
D
可以想一个 dp
,划分段,一段贡献最长不下降子序列,其他段贡献 \(0/1\),一位一位选择可以做到 \(\mathcal O(n^2)\)。
考虑更优的转换:找出一个子序列,使其缩起来后段数 \(\le k+1\),那么他的长度可以贡献段数为 \(k\) 的答案。
可以发现答案具有凸性,再分析一下固定子序列的最左和最右颜色,也是凸的。
于是闵可夫斯基和和合并即可。
322.P6672 [清华集训2016] 你的生命已如风中残烛
如果 \(x_1,x_2,\cdots,x_m\) 是任何一个和为 \(1\) 的整数数列,则其所有循环位移中恰好有一个满足所有的前缀和都是正数。
扩展:和为 \(s\) 有 \(s\) 种。
考虑证明卡特兰数,在前面加上 \(a_0=1\),这样就能运用这个定理了。
因为互不区分,所以此时方案数为 \(\frac{\binom{2n+1}{n}}{2n+1}=\frac{\binom{2n}{n}}{n+1}\),分母指的是一种相同的等价类有 \(2n+1\) 种方案,然后因为得出的方案开头一定是 \(1\),所以扣掉这个 \(1\) 就行了。
再考虑这道题。
先做转化,对于一张 \(w_i\) 的牌,效果是使牌增加 \(w_i-1\),对于普通牌,效果是牌数 \(-1\)。
转化后要求的是牌排列方案数(区分),使得前缀和 \(\ge 0\)。
考虑用上面的方法,使 \(a_0=1\),但是这样就不行了,因为得出的方案开头不一定是 \(1\)。
考虑在末尾添加 \(a_{m+1}=-1\),再将所有数取反,此时序列和为 \(1\),原序列前缀和 \(\ge 0\),新序列前缀和 \(\le 0\),则新序列后缀和 \(>0\),从后往前看,运用上面的定理,发现次数最大的数一定是 \(1\),做完后得出的方案开头一定是 \(1\)。
一共有 \((m+1-1)!\) 中圆排列,原本有 \(m-n\) 个 \(1\),排列数是 \((m-n)!\),现在是 \((m-n+1)\) 个 \(1\),排列数变成了 \((m-n+1)!\),除掉多的就好了。
323.CF1969
C
显然贪心不太好做。
考虑 dp
,最终数组的形态一定是有若干段被覆盖的区间,每一段都被相同的数覆盖。
设 \(f_{i,j}\) 表示考虑到 \([1,i]\) 可以使用 \(j\) 次,转移考虑右端点为 \(i\) 的 \(\mathcal O(k)\) 个区间,每个区间显然用最小值覆盖最优。
时间复杂度 \(\mathcal O(nk^2)\)。
D
按照 \(b_i\) 从大到小排序,那么最优方案等价于前缀 \(a_i\) 的前 \(k\) 小加上后缀的 \(\max(0,b_i-a_i)\) 的和。
E
考虑贪心,从前往后加数,扫描线,维护所有左端点的唯一数个数,当不合法时,断开,容易证明。
修改考虑加入的这个数的前两个前驱即可。
F
考虑如果当前有两个相同的数,将其打出是最优的,证明考虑否则更换后面打出这两张牌的操作,一定可以调整。
考虑特殊局面,即 \(1\sim k\) 都出现了,此时没有贡献。
设 \(f_i\) 考虑考虑到 \([1,i]\) 特殊局面出现次数的最小值。
考虑枚举所有后继状态,计算下一个特殊局面的位置,时间复杂度 \(\mathcal O(n^4)\)。
但是发现“下一个特殊局面的位置”只有 \(\mathcal O(n)\) 个,一定是出现且只出现了两个出现次数为偶数的颜色,这样后继状态选择这两个颜色就停止了,时间复杂度优化到 \(\mathcal O(n^2\log n)\)。
注意到还需要计算到序列为空时的局面(即没有下一个特殊局面)的情况的后继状态的贡献,显然贡献为最后出现次数为奇数的数的个数(这道题真的很神奇,\(n,k\) 都是偶数,只需要考虑出现次数奇偶次数,无需考虑打出牌组等一堆细节!!!。
发现只有三类,就是使得出现次数为奇数的个数 \(-2\),不变或 \(+2\),计算一下这三类的个数,除去一定有下一个特殊局面的后继状态即可。
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18393886