2024.11 做题记录 / 把心塞进污垢 封锁所有出口
P11013
首先有一个观察,答案只跟最后一次操作的右端点位置有关,可以做到上一次操作放在序列的一端,别的全都放在另一端之后全部消除,得到消除 \(r\) 个的优异战绩。
现在我们只关心第 \(i\) 个位置出现时能否发生消除,不妨设这个为 \(f_i\),然后设 \(pre_i\) 表示上一个 \(a_i\) 出现的位置,首先比较天然的可以从 \(f_{pre_{pre_i}}\) 转移,这个是 \(pre_{pre_i}\) 之后不动就行了,然后还有可能是 \(pre_{pre_i}\) 被消除了导致 \(pre_i\) 和 \(i\) 能匹配上,这要求 \(f[pre_{pre_i},\dots,pre_i-1]\) 中有为真的,前缀和优化即可。
P6047
废话但基本的,切割一条弦 \((i,j)\) 相当于选择 \(i\in[1,X_i-1],j\in[Y_j+1,n]\) 的 \(a_i\times b_j\)。
比较明显的,有交叉的弦一定是偏序的,具体而言对于一对弦 \((x,y),(X,Y)\) 满足 \(x\leq X,Y\leq y\) 那么能切割 \((x,y)\) 的一定能切割 \((X,Y)\) 那么可以去掉后者,这样处理之后得到的弦都是不相交的,很方便 dp。
考虑 \(f_i\) 表示切割掉前 \(i\) 条弦的 mincost,更改 \(a/b\) 的定义为其前/后缀和,那么转移显然是 \(f_i=f_j+a[x_{j+1}-1]\times b[y_i+1]\),对于这个 \(±1\) 题目有保证不用考虑,斜率优化即可。
P3527
比较一眼的主席树 + 二分,但是也有整体二分的做法。
主席树 + 二分的话是用主席树预处理出历史单点和,查询就二分暴力查询就是了。二分的次数是 \(\log k\),然后暴力查询复杂度是 \(count(id)\times \log\),因为 \(\sum count(id)=m\),总的复杂度就是 \(O(m\log k\log m)\)。
整体二分的话跟上面同理,暴力查询次数只有 \(m\log k\),整体二分的时候上一棵树状数组就行了。
P6684
先考虑怎么判定有没有奇环,生成树什么的还是太超模了。没有奇环那就是二分图,我们用拓展域并查集判定二分图即可,这个是容易写可撤销的。具体而言对于一个点建立两个点 \(A_i/B_i\) 表示这个点放在某个集合的命题,对于一条边 \((x,y)\) 建边 \((A_x,B_y),(A_y,B_x)\) 即可,这两个命题不同时成立就是二分图。
直接做 \([1,l]\cap [r,n]\) 显然不太实际,不难发现钦定 \([1,l]\) 之后合法的 \(\min\{r\}\) 是区间且单调,可以双指针,问题是删除需要上 lct,这太困难了。考虑到这个其实也可以二分那么不妨上一个整体二分,发现只要稍微钦定一下加鞭的顺序复杂度就对了,代码懒得写了 qwq
AT_agc030_e
不是很难题。首先不能有子串 \(\text{000/111}\) 说明 \(0\) 旁边一定有 \(1\),\(1\) 旁边一定有 \(0\) 这样子。
不妨考虑 \(01\) 交替的划分线,假设序列两端有无限制的划分线,问题转换成想调整划分使得两个序列划分相同,有一个奇偶性的限制,发现枚举划分开头按照大小对应贡献即可。
P2056
两个 shaber 错误调了一个晚上(不过竟然只有两个错误的嘛),真出生啊,太歹毒了。不过这题这个括号序列的做法还是挺神仙的,感觉不看题解不太能做,真的不知道正常人怎么会往这个想的。
首先先把树转成 带数字 的括号序列,比如样例就是 \(\text{(1(2(3(4)(5)(6(7)(8)))))}\),那么两个点之间的距离就是两个对应数字之前的括号序列的不能匹配的括号数量,假设这两个数是 \((x,y)\),考虑一个 \(z\gets LCA(x,y)\),那么 \(x\to z\) 只有 \(\text{')'}\),剩余的部分只有 \(\text{'('}\),用栈去推序列匹配数肯定是最大的,这个过程中显然非路径点一定匹配到原来的,路径上点一定没有匹配。
现在考虑怎么维护 \(\max_{l<r,str_{l/r}\in Number}\{dis(l,r)\}\) ,括号的匹配是支持区间合并的 (按照栈匹配容易分析出等价性)且题目要求带修,不妨考虑线段树。首先肯定要维护区间 \((L,R)\) 表示自然收缩后变成
这样子,然后必须维护区间答案 \(Ans\)
,然后要维护前后缀拼接的答案需要知道区间后缀/前缀的最优答案。
考虑拼接前后缀是什么东西
和
拼接在一起的不合法序列长度是 \(L_1+R_2+\max(R_1-L_2,L_2-R_1)\),因为取到最大值的一定是合法情况不妨分别维护 \((L_1+R_1)+(-L_2+R_2)\) 以及 \((L_1-R_1)+(L_2+R_2)\) 然后取较大值,维护四个括号里面的 \(\max\) 分别为 \(qz,hz,zq,zh\) 就可以合并了。
初始化的细节就是不存在的东西要初始化成 \(-\infty\) 因为要求贡献区间左右端点都是数字。按照定义往上面写就行了。pushup 的话,\(a/b/Ans\) 按照上述定义/拼接写就行了,剩下四个恶心玩意儿也是按照拼接分讨写上去。最后就是,数组要开的足够大。
P8293
这个直接做括号感觉不太可行,这种走投无路启发我们把这个转成树上问题,就是把括号序列当成 dfn 序,匹配的一对括号对应一个节点的入和出。
因为 \(\text{AB}\) 都是合法序列也就是完整子树,不喜欢的结构 \(\text{(A)(B)}\) 其实就是要求不能有一个点有两个儿子,那么就是想要一条链。操作二就是子树儿子顺序随意,操作一在结合了操作二的情况下就是选择一个点的儿子 \(u,v\),把 \(v\) 的儿子树和 \(v\) 分别接在 \(u\) 的儿子处。这个操作一定调高了 \(v\) 的深度,所以深度从小到大调整一定是不劣的,否则一定可以找到符合的方式替代,假设你在中间部分做了一次操作,你把深度比这个小的操作先做一下不会影响你做这个的说。
至此完成了题目的初步转换,可以开始分讨了,下文 \(siz\) 表示当时层里面的节点数 >w<
- \(x=0,y=0\)
怎么操作都不会产生代价,直接输出 \(0\) 就行了,但是貌似没有这一档的分。
- \(x=0,y=1\)
操作移动到下一层的点会贡献一次权,留在本层的点没有贡献,这个显然贪心每次留下最大权的点就行了。可以用 priority_queue/multiset 之类的随便维护一下。
- \(x=1,y=1\)
考虑留下的点为 \(x\),权最小的点为 \(y\),别的点集是 \(\{p\}\),最好代价显然是 \(|p|\times V_y+\sum V_{p_i}+V_x+V_y=\sum V_i+(siz-2)\times V_y\),更充分的说明是, \(x=y\) 写一下可以发现不优。这个也很好贪心喵,每次留下最大的就行了,还是拿着你那 multiset 维护一下。
- \(x=1,y=0\)
还是先分析贡献是什么,类似于上一种情况去算,这部分是 \(V_y\times (siz-2)+V_x\),注意到除了链尾的那个点别的点都一定要被当成 \(x\) 贡献一次 \(V_x\),那么我们希望「下放最小值多蹭一点 \(V_y\) 的贡献」以及「下放最大值尝试去蹭最后一个 \(V_x\) 的没有贡献 」,如果 \(siz>2\) 那肯定两者都无脑下放肯定不劣,如果 \(siz=1\) 肯定没有贡献,问题在于怎么处理 \(siz=2\) 的情况。
首先,如果 \(siz>2\) 了,以后只会有一次 \(siz=2\) 的情况。如果下一层有节点,那么 \(siz\) 单调不降,否则以后下一层都没有节点,会按照 \(siz=siz',siz'-1,\dots,3,2,1\) 这样子变化。在这部分前面如果又碰到 \(siz=2\) 因为那个单调不降应该是一串 \(siz=1,1,1,\dots,2,2,2\) 这样。 我们去掉不用考虑的前缀 \(siz=1\) 的部分,考虑一下 \(siz=2,\dots,2,\dots(\geq3),3,2,1\) 这样子的序列怎么贪心。
发现前面一串 \(siz=2\) 的贡献是 \(点权和-留下点的权值\),只用考虑留下的是这部分的最大值还是最小值就可以了,后面只会碰到一次肯定保留最小值的 \(siz=2\) 的贪心。因为如果下面有比这个局部最大值更大的权这个局部的肯定会被抛弃,那么不妨直接考虑留下全局最大值的情况。
P5244
提前加入 \((0,0),(T,T)\),首先因为只能向右/上走且钦定了速度相同,设拿到的点序列是 \(p_0,\dots,p_{len}\),割掉的草的面积一定是 \(p_{i},p_{i+1}\) 组成的矩形面积和 \(\sum_{i=0}^{len-1}(X[p_{i+1}]-X[p_i])\times (Y[p_{i+1}]-Y[p_i])\),显然这样子最大。首先要最大化 \(|p|\),设这个类似 LIS 的东西的长度为 \(g\),按照 \(g\) 的值分层,只有上一层能往下一层转移,可以保证满足这个约束,同时因为同层之间一定互不转移,按照 \(x\uparrow\) 去看一定有 \(y\downarrow\) 这个条件。
现在考虑相邻层的转移 \(A\to B\),怎么从一层的 \(A=\{(x,y,f)\}\) 更新 \(B=\{(x,y,f)\}\) 中 \(B\) 的 \(f\),这里 \(f\) 是到某个点的最小切割面积。转移方程是 \(f_B=\min_{x_A\leq x_B,y_A\leq y_B}\{f_A+(x_B-x_A)\times(y_B-y_A)\}\),上文提到 按照 \(x\uparrow\) 去看一定有 \(y\downarrow\) 这个条件,这种感觉多半跟决策单调性挂钩,这个直接函数意义上不太好分析,我们回归最原始的定义,考虑什么时候对于转移到 \((X,Y)\) 来说 \((x_1,y_1)\) 比 \((x_2,y_2)\) 优秀,不难写出以下柿子 >w<
注意到这个柿子左边是定值,\(y_1-y_2/x_1-x_2\) 一正一负,\(X/Y\) 变化是反的,确实有决策单调性,但是是反的???
我们 reverse 一下 \(A\) 然后变成带着只能在某个区间里面转移的决策单调性,注意到我们要的是单点对单点的 \(\min\),我们容易考虑分块,考虑一个 \(B_i\) 可以从 \(A[l,\dots,r]\) 转移过来,这个可以二分求出,那对 \((l,r)\) 做嘛,对于非整块暴力,对于整块按顺序打上标记,再在每一块上面做一次普通的决策单调性,然后把贡献放到点里面。分块还是太暴力了,注意到很容易类似的放到线段树上面,那么考虑类似的做法上线段树即可,复杂度 \(O(n\log^2n)\),因为一个询问分成 \(\log\) 段,每一段都做 \(\log\) 次 。
P3514
如果只有一个询问暴力的话会想双指针,首先先考虑 \(\sum_{i=1}^{pos} arr_i\leq x\) 的最大 \(pos\),从这里开始考虑,设当前右端点为 \(r\),拓展一个 \(arr_{r+1}=1\) 就合法了,如果拓展一个 \(arr_{r+1}=2\) 则要移动左端点,此时如果 \(arr_{l}=1\) 那就合法了,综上所述只有当 \(arr_{l+1}=arr_{r+1}=2\) 的时候才不能拓展出合法的。
现在要快速查询,而分出 \(pos\) 还有两个需要的 \(2\) 的连续段即可,直接在断点的地方判定一下就行了,需要一个前缀和优化。
P5749
先考虑鞋子的匹配关系,\(|s|\) 不同的显然不匹配,如果有多对 \(|s|\) 相等的,那么应该按照在对应正负性出现的排名来匹配,因为交叉一定不优。然后考虑鞋子对最终的顺序应该是什么,因为交叉不优还是按照顺序往前放不劣,给出最终位置之后用树状数组辅助求一下逆序对数即可。
AT_arc155_d
如果强制 \(G\) 变化那么输赢是好求的,设 \(f_i\) 表示拿到 \(G=i\) 的情况是不是必胜的,转移显然有 \(f_i=\text{OR}_{\exists 1<j<i,\gcd(a,i)=j} \{¬ f[j]\}\)。然后考虑 \(G\) 不变化的情况,首先递推的时候未来的贡献未来已经做好了只用考虑当下,如果碰到必败局面两个人会不停的试图让 \(i(G)\) 不变直到没有可以使 \(i\) 不变的数,这个好像需要知道未来用掉了多少个 \(i\) 的倍数,这个是记不了的,但是我们只关心奇偶性,在必败局面放上这个贡献即可。
问题是怎么判断一个 \(j\) 是不是合法的,考虑容斥(其实也可以莫反),设 \(s_j\) 为 \(a\) 中 \(j\) 的倍数个数,\(g_{i,k}\) 表示 \(\gcd(i,a)=k\) 的 \(a\) 的个数,那么对于可能的 \(j|i\),因为 \(j|a\to j|\gcd(a,j)\),应该有 \(s_j=\sum_{j|k} f_{i,k}\),移动一个 \(f_{i,j}=s_j-\sum_{j|k,j\neq k}f_{i,k}\),可以递推了,暴力一点但别太离谱就行了,复杂度不超过 \(O(\sum (d_i)^2)=O(n\log^3n)\),这里 \(d\) 是约数个数,但是在 \(O(n\log^2n)\) 以上,具体怎么算我就不知道了。
P2490
不妨 \(k\gets \frac{k}{2}\),设白黑棋子间可以缩小的间隔分别为 \(a_1,\dots a_k\),那么操作就是每次选择 \(x\in[1,d]\) 个 \(a\) 使其严格变小,不能操作的人失败。我没有力气和手段自己发明创造出来这个 \(d-nim\) 问题的解法所以我选择介绍一下结论和证明。
用 \((x)_y\) 表示 \(x\) 二进制下第 \(y\) 位的值,我们声称 \(\forall x,\sum_{i=1}^k(a_i)_x\mod{d+1}=0\) 的局面必败,反之,\(\exists x,\sum_{i=1}^k(a_i)_x\mod{d+1}\neq 0\) 的局面必胜。注意到这是一个 DAG 上的游戏,那么能到达必败态的是必胜态,不能到达必败态的是必败态,我们可以证明这个。
-
必胜态能到达必败态:注意到一个 \(a\) 如果在一个二进制位 \(1\to 0\),那么后面的位随便变化 \(a\) 都是变小的。动态维护变化了的数的集合,按照二进制位从高到低考虑,在集合里面暂时随便额外加入当前位为 \(1\) 的数直到没有这种数或者集合大小为 \(d\),如果最后集合大小没有达到 \(d\),当前位为 \(1\) 的肯定都加进去了,那么随便选一些 \(1\to 0\) 一定是够的,下面考虑集合大小是 \(d\) 的情况,当前集合当前位为 \(1\) 的使用 \(1\to 0\) 肯定没有问题,当前集合当前位为 \(0\) 的一定是以前在某一位下降过的所以使用 \(0\to 1\) 肯定没有问题,设有 \(d-x/x\) 个当前位为 \(1/0\) 的,可以造成的影响区间显然是 \([-x,d-x]\),这个显然可以帮助这一位的和在 \(\mod{d+1}\) 意义下碰到为 \(0\) 的,最后再删除集合中从来没有下降过的数即可
-
必败态不能到达必败态:\(a_i\) 一位上的扰动一定在 \((-d,d)\) 之间,不能够到两边的 \(0\),更不能全都是中间的 \(0\)
显然必败态数量更好考虑,不妨用总方案数 \(\binom{n}{2k}\) 减去必败的方案数。然后就是要考虑怎么 dp 了,不妨按照二进制位来考虑,设 \(f_{i,j}\) 表示考虑了二进制下 \((\infty,i]\) 位 \(\sum a=j\) 的方案数,初始化显然是 \(f_{\infty,0}=1\)。转移的话考虑当前位使用了 \(p\) 个 \(1\),要求 \(d+1|p,0\leq p\leq k\),转移有 \(f_{i+1,j-2^i\times p}\times\binom{k}{p}\to f_{i,j}\),最后的答案显然是 \(\sum_{i=1}^n f_{0,i}\times \binom{n-i-k}{k}\),组合数是插板来的。
然后说句鲜花,感觉 nim 注重二进制本质上是转化成并行的 \(0/1\) 的游戏 ......?
P9871
模板题。
首先朴素 dp 的话,设 \(f_{i,j}\) 表示第 \(i\) 天连续打卡了 \(j\) 天的最大能量值,转移有 \(f_{i,0}=\max_{j\in[0,k]}\{f_{i-1,j}\},f_{i,j}=f_{i-1,j-1}\),然后考虑一个打卡 \((t,x,v)\) 的贡献,对于 \(j\geq x\) 有一个 \(f_{t,j}\gets f_{t,j}+v\)。
很难不发现这个可以线段树优化 dp,用 \(pos-t\) 来当下标非常的对,区间加是平凡的,你考虑如何 \(f_i\to f_{i+\Delta}\),前面的 \(\Delta\) 个初始化成公差为 \(d\) 的等差数列,然后就是 \(O(m)\) 个区间加。初始化可以做 dp 前直接初始化原序列为等差数列然后转换成区间加,用主席树维护可以做到 \(O(m\log n)\) 这样子,但是常数和复杂度都不够好,注意到只有连续打卡 \(0\) 天和被 \((t,x,v)\) 的 \(x\) 切割过的 \(x-t\) 才是贡献的,离散化可以做到 \(O(m\log m)\),代码还更好写一点。
P9120
充分发扬人类的智慧,发现按照默认顺序得到最优解的概率已经很大了,那么再加一个 random_shuffle + 贪心。