2024.2.20 近期练习
P4766 [CERC2014] Outer space invaders
不难发现时间的先后顺序是不重要的。所以把时间转化到数轴上。
数据范围提示区间 dp,设 \(f_{l,r}\) 表示 \([l,r]\) 时间里面全部消除的代价。
\(f_{l,r}=\max(f_{l,k}+f_{k,r}+d_{l,k,r})\),其中 \(d_{l,k,r}\) 表示跨越 \(k\) 的,且在 \([l,r]\) 里最远的距离。
然而 \(d\) 的处理要四次方。
考虑钦定一个区间内距离最远的最后消除,\(O(n)\) 找到 \(id\),
那么 \(f_{l,r}=\max(f_{l,k-1}+f_{k+1,r}+d_{id})\),满足 \(k\) 在 \(id\) 这个区间里。
这种问题区间 dp,以及要学会钦定。
P5933 [清华集训2012] 串珠子
设 \(f_S\) 表示 \(S\) 任意连边的方案数,\(g_{S}\) 表示 \(S\) 点集联通的方案数。
考虑容斥,求出 \(h_S\) 表示 \(S\) 点集不合法的方案,\(g_S=f_S-h_S\).
我们对于 \(h_S\),为了不重复,先随便取出一个点 \(p\),枚举 \(p\) 所在连通块 \(P\),设 \(T=C_SP\).
那么 \(h_s=\sum dp_P\times f_T\),\(T\) 不能为空集。
这种问题经典容斥,类似枚举第一个非法。
P4198 楼房重建
我们要维护的是一个下凸壳,则每个点到原点的斜率递增。
线段树维护,我们假设现在线段树维护好了一些区间,如何去合并。
关于合并两个区间,首先要记录一个区间的最大斜率 \(Mx\) 和凸壳点的个数 \(len\)。
左边区间必选,我们现在要找右边的第一个斜率大于左边 \(Mx\) 的点,给它接上去。
线段树上二分。如果往右走,那么继续递归;往左走,加上右边的贡献,是 \(len_p-len_{ls}\).
经典线段树,即 merge 要带 \(\log\).
P5307 [COCI2018-2019#6] Mobitel
首先有朴素的状态 \(dp_{i,j,k}\) 表示到 \((i,j)\) 这个点,当前乘积是 \(k\) 的方案数,明显裂开。
考虑优化状态,\(dp_{i,j,k}\) 表示还要至少乘上 \(k\) 才能不小于 \(n\) 的方案数。
整除分块,\(k\) 的个数是 \(\sqrt n\) 级别的。
这种问题是优化了状态设计,运用到乘法的性质。
P3863 序列
由于是单点查询,考虑扫描线,滚下标这一维,顺便维护当前每个时间点的值。
考虑把修改差分,变成时间这一维区间修改。
我们要询问的,也就是区间排名,考虑分块完成即可。
这种问题要考虑变化维度,往往时间这一维是容易被忽视的。
P4921 [MtOI2018] 情侣?给我烧了!
钦定 \(f(k)\) 表示钦定 \(k\) 个满足条件的方案数,\(f(k)=C_n^kA_n^k2^k\)。
我们求 \(g(k)\) 表示恰好 \(k\) 个满足条件方案数,\(f(k)=\sum_{i=k}^ng(i)\times C_n^i\),
那么反演,\(g(k)=\sum_{i=k}^n(-1)^{i-k}C_i^kf(i)\).
组合数拆开,\(g(k)=\dfrac{2^k(n!)^2}{k!}\sum_{i=0}^{n-k}\dfrac{(-1)^i2^i(2n-2k-2i)!}{i!((n-k-i)!)^2}\).
我们预处理右边那个和式就行了。
注意钦定不是至少,钦定会重复。故 \(g(k)\neq f(k)-f(k+1)\).
这是二项式反演的经典,注意钦定不是至少。
P5439 【XR-2】永恒
先考虑 \([u,v]\) 这个点对的贡献,显然被计算了 \(siz_u\times siz_v\) 次。
若二者有祖先关系,钦定 \(u\) 为祖先,那么算了 \(siz_v\times (siz_{fa(u)}-siz_u)\) 次。
同时我们发现,字典树上 \(lca\) 深度就是 \(f(lcp)\) 的值。
逐个扫一遍,设目前维护了已经扫过的集合,新加入一个点计算贡献。
设 \(s_i\) 表示新加的点在字典树上从浅到深第 \(i\) 个点子树里扫过的点的贡献。
那么贡献为 \((s_1-s_2)+2(s_2-s_3)+3(s_3-s_4)...=\sum s\).
所以支持链加和链求和即可,树剖。
分祖先关系情况计算即可。
这个题就是扫描线罢了。
P5309 [Ynoi2011] 初始化
很显然是根号分治,若周期大于 \(\sqrt n\) 的,直接暴力修改,由于查询区间和,考虑分块。
若周期不大于 \(\sqrt n\),就不能直接修改了。
对于单点,我们很容易可以枚举所有 \(\le \sqrt n\) 周期,计算贡献。然而区间查询呢?
我们可以对于每个周期的每个起始位置的贡献,用前后缀和维护,可以 \(O(1)\) 计算、
这个题是经典的根号分治。
P7503 「HMOI R1」文化课
一个很朴素的 dp,设 \(f_i\) 为以 \(i\) 结尾的答案,\(f_i=\max(f_{j-1}+w(j,i))\),
其中 \(w_{j,i}\) 表示在 \([j,i]\) 举办作弊的效益。
我们递推 \(i\) 的时候,能否顺便地更新 \(w_{j,i}\) 呢?实际是很难的。
考虑正难则反,对于 \(j\),计算其能对哪些 \(i\) 贡献。
我们考虑计算出对于一个点 \(i\),其能起贡献的区间,这个可以二分 ST 表或树状数组。
然后扫描线,用线段树维护 \(w_{j,i}\),只需要支持区间加、询问 \(\max\)。
这个题正难则反,转换,把填表法变成刷表法。
P8253 [NOI Online 2022 提高组] 如何正确地排序
一眼 min-max 容斥。
对于 \(m=4\) 的来说,\(\max_S+\min_S = (\sum_{T\subseteq S}(-1)^{|T|-1}\min_T)+\min_S\),刚好消去 \(\min_S\),
故 \(m=4\) 的可以转化为 \(m\le 3\) 的。然而 \(m=3\) 的无法再继续转化了,因为无法抵消。
\(m\le 2\) 的很显然,现在问题转化为 \(m=3\) 怎么做?我们把 \(\min,\max\) 先拆开,先计算 \(\max\)
钦定第一维的最大,那么 \(a_i+a_j\ge b_i+b_j,a_i+a_j\ge c_i+c_j\)。
故 \(a_i-b_i\ge b_j-a_j,a_i-c_i\ge c_j-a_j\)。二维数点即可。
这个题,经典 min-max 容斥,再转为偏序问题。
P7323 [WC2021] 括号路径
对于一个合法路径,势必有两个相邻的左右括号,我们从这里入手。
如果存在一个长度为 \(2\) 的合法路径 \((x\to z\to y)\),那么 \(x,y\) 已经等价,可以直接合并。
考虑用并查集来处理,一直合并,直到不能再合并了。
并查集的典型运用,合并同类项,从小任务到大。
P6847 [CEOI2019] Magic Tree
考虑设计一个暴力的 dp。设 \(dp_{u,t}\) 表示在 \(t\) 秒割掉 \(u\to fa_u\) 的边的最大收益。
\(dp_{u,t}=w_u\times[d_u= t]+\sum \max_{k\le t} dp_{v,k}\).
设 \(f_{u,t}=\max_{k\le t} dp_{v,k}\),那么,或 \(f_{u,t}=\max(\sum f_{v,t},w_u+\sum f_{v,d_u})\).
\(f\) 数组单调,且有若干连续段是相等的,维护断点。
然而有区间加操作,不如维护 \(f\) 的差分数组。用 map 启发式合并即可。
启发式合并,差分优化。
P5749 [IOI2019] 排列鞋子
考虑贪心,从左往右配对,每次取左边第一个没配对的,用最靠近它的移过来配对。set 维护。
已经配对的,可以删去。用树状数组维护前缀和来计算位置。
贪心,同时运用了删除不必要元素的思想。
P6186 [NOI Online #1 提高组] 冒泡排序
考虑冒泡排序的本质,就是从左到右每次找当前最大的,放到比这个数更大的位置前。
思考这与逆序对的关系,设 \(c_i\) 表示第 \(i\) 位与前面构成多少逆序对。
经过一轮的冒泡排序,\(c_i=\max(c_{i+1}-1,0)\),我们稍微维护一下即可。
冒泡排序分析。
P2824 [HEOI2016/TJOI2016] 排序
普通排序很慢,考虑给 01 串排序,如果用线段树维护是 \(O(\log n)\) 的。
考虑二分 \(mid\),把 \(\ge mid\) 的设为 \(1\),否则设为 \(0\),只需要看最后该位的取值。
单调性?基于比较的操作,故具有单调性。
神仙。基于比较考虑二分。
P3295 [SCOI2016] 萌萌哒
考虑暴力的 \(O(nm)\) 并查集,时间被浪费是因为合并了已经合并的点。
一眼线段树处理,拆分区间。但实现难度大,所以我们可以考虑上倍增。
倍增 \(f_{k,i}\) 表示 \([i,i+2^k-1]\) 的父亲,类似 ST 表那样去合并。
还有一种方法,线段树维护哈希二分出第一个没有合并的位置去合并。

浙公网安备 33010602011771号