CF1239D Catowice City

由 "第 \(i\) 个人和第 \(i\) 只喵一定认识",于是形成了第 \(i\) 个变量要么选人要么选喵的 \(\text{2-sat}\) 形式。对于 "第 \(i\) 个人和第 \(j\) 只喵一定认识" 的限制,就相当于 "\(i\) 选人那么 \(j\) 不选喵" 实际上也就是 "\(i\) 选人那么 \(j\) 选人"。它的逆否命题就是 "\(j\) 选喵那么 \(i\) 选喵",这题比较特殊,因为可以发现选人与选喵的两类虚点压根没有连边,而且形成的两张图是对称的,所以完全可以去掉选喵的虚点。

现在将图缩成若干个强连通分量,首先同一个强连通分量要么全选人要么全选喵。若强连通分量 \(x\) 拓扑序在 \(y\) 之前,那么若 \(x\) 全选人,\(y\) 也必须全选人。由于题目要求选人选喵均存在,所以直接令拓扑序最大的强连通分量全选人,其余选喵即可。

CodeChef: BINLAND

一些闲话:记得当初调这题鬼冒火,题解就一直咕着(,时隔十个月后终于消气了 🙁。

首先,路径条数可以用 \(\mathcal O(n^2)\)\(\mathtt{dp}\) 搞出来。一边删除一边插入?这使我们不由得想到了用双栈维护。而且非常高兴的是,这题并不像 \(\text{LOJ - 6515 }\)贪玩蓝月 一样,两端都可以插入删除,所以我们用栈 \(1\) 先维护添加的行,当需要删除时,若栈 \(2\) 为空,就直接把栈 \(1\) 的所有元素插进栈 \(2\),这样暴力做的复杂度是线性的(不考虑 \(\mathtt{dp}\) 数组的维护)。

基于这个操作,我们考虑如何维护 \(\mathtt{dp}\) 数组:由于在栈 \(1,2\) 都有值的情况下,需要将信息拼起来,所以不妨用 \(dp(i,j,k)\) 表示当前处在栈的第 \(i\) 层(从栈底至上),从栈底的 \(j\) 列到达这一层的 \(k\) 列的路径条数。这样插入一行是 \(\mathcal O(n)\) 的,合并也是 \(\mathcal O(n)\) 的。总时间复杂度 \(\mathcal O(qn)\).

[Contest on 2022.7.1] 征服

题意简述:地图上共有 \(n × m\) 座城池,抽象到一个 \(n × m\) 的棋盘上,每个格子代表一个城池。 其中有一些是核心城池(用字符 X 代表),其他的是普通城池(用字符 . 代表)。

两位玩家轮流行动,每轮行动的玩家可以选择一个 未被占领的核心城池。占领该城池后,该玩家的势力会从这个城池向左上,右上,左下,右下四个 \(45^\circ\) 方向进行扩张:

  1. 如果当前已经扩展到边界,沿着这一方向的扩展结束;
  2. 如果当前城池已被任意一个玩家占领,沿这一方向的扩展结束。

\(T\leqslant 10,1\leqslant n,m\leqslant 100,nm\leqslant 200\).

首先棋盘可以被划分成奇偶两部分,每个部分再转 \(45^\circ\),就可以得到两个矩形状物。这时可以发现,占领一个核心城池实际上相当于将矩形横纵切一刀,分成四个矩形。于是用 \(\rm sg\) 定理即可递归求解。复杂度 \(\mathcal O(n^3m^3)\),这是因为枚举转移点也有复杂度。

Easy String Problem

考虑先画出两个结果相同的删除方案,假设删除区间为 \([l_1,r_1],[l_2,r_2],l_1\leqslant l_2\),可以发现 \([l_1,l_2)\)\((r_1,r_2]\) 区间是完全相等的。由此可以证明一个结论:对于区间为 \([l,r]\) 的询问,答案就是总区间选择方案减去 \(\sum_{i=1}^l\sum_{j=r}^n [a_i=a_j]\),于是直接用莫队维护,复杂度根号。

如何证明?首先减去相同颜色对数可以看作是两个删除区间满足 \(l_2=l_1+1,r_2=r_1+1\)。对于其它的删除区间,容易发现它一定存在于上述二元组中,所以已经被去重了。

CF626E Simple Skewness

喵喵题。

首先可以证明选择偶数个是不优的,为了简化证明过程,可以对当前选取的集合 \(S\) 做一个操作:设此集合排序后最中间两个数为 \(l,r,l\leqslant r\),将集合中所有数减去 \(l\),记此时集合元素之和为 \(s\),可以发现平均数减去中位数的值(下文称其为集合的权值)仍然不变,为 \(\displaystyle s/|S|-(0+r)/2\).

另外也可以发现,\(s\) 一定大于零,否则集合的权值一定 \(\leqslant 0\),那么这个集合一定不优于只选一个元素的集合(选择奇数个)。否则我们去掉 \(r\),此时集合的权值变成 \((s-r)/(|S|-1)-0\)。不妨假设去掉 \(r\) 的集合权值更大,这等价于

\[2s>|S|\cdot r\cdot (3-|S|) \]

由于 \(|S|\geqslant 3\)\(\leqslant 2\) 的情况可以单独讨论),所以右式恒 \(\leqslant 0\),而左式恒大于零,所以原假设成立。

于是可以枚举中位数 \(x\),最大化选取集合的平均数,且 \(x\) 两边的数字个数必须相等。容易想到二分 \(x\) 右边选取的数字个数,如何选取?实际上就是第一次选取序列最大值和小于等于 \(x\) 的最大值、第二次选取序列次大值和小于等于 \(x\) 的次大值,依此类推……

每次加入一个数对,可以用它们的平均值刻画对已选集合的影响,如果平均值大于已选集合的平均值,加入就能增加集合的平均值,反之只会更劣。这个位置就是需要二分到的点。

复杂度 \(\mathcal O(n\log n)\).

[HEOI 2012] 朋友圈

一个非常有用的结论:原图的最大团等于补图的最大独立集。我就不写了

AT1219 - 歴史の研究

回滚莫队板题。所以我们要讲解非回滚莫队做法 😘。

本题无法直接莫队的原因就是删除最大值后,无法快速找到当前最大值。事实上,可以先对第 \(i\) 类事件预处理 \(i,2i,\dots, \text{cnt}_i\cdot i\),将所有事件的这些值离散化排序,在这个数组上做值域分块即可。这么看来,求 \(\rm mex\) 的回滚莫队也可以用值域分块做了(好像没啥用啊。

[UNR #2] 积劳成疾

一些闲话:突然开始慌张了。

突然发现很多 "某状态权值为乘积,求所有状态和" 的问题,好像都可以用乘法原理压缩状态。对于此题,你会发现权值和只和题目数量有关,于是可以设 \(dp(i,j)\) 为有 \(i\) 道题,最大值为 \(j\) 的答案,转移就枚举最大值第一次出现的位置即可。为了方便转移,可以将第二维定为最大值 \(\leqslant j\) 的答案,转移

\[dp(i,j)=dp(i,j−1)+\sum^i_{p=1}w^{\min(p,i−k+1)−\max(1,p−k+1)+1}_j\cdot dp(p−1,j−1)\cdot dp(i−p,j) \]

[NOI 2018] 你的名字

一些闲话:拖到这个时候才来做经典题的笔者是……什么呢?

是 SAM 做法。\(n=|S|,m=|T|\)。首先考虑询问 \(l=1,r=n\) 的情况,这就是算 \(T\)\(S\) 中的所有 本质不同不共同 子串。做一个容斥也就是 \(T\) 的所有本质不同子串减去与 \(S\) 的本质不同共同子串。

\(T\) 的所有本质不同子串可以直接在建树的时候求,假设当前新建叶节点为 \(cur\),新增本质不同子串数就是 \(\text{len}_{cur}-\text{len}_{\text{fa}_{cur}}\),这个还是很好理解的。同时,再记录 \(\text{sub}_i=\text{len}_{\text{fa}_{cur}}\).

现在考虑求与 \(S\) 的本质不同共同子串数。把 \(T\) 放在 s-SAM 上跑,假设当前节点为 \(p\),加入字符 \(c\) 时,一直跳 \(p\)\(\rm fa\) 直到 \(p'\) 有儿子 \(c\),然后走到对应儿子 \(q\)。那么以 \(t_i\) 为末尾的贡献就是 \(\text{len}_q-\text{sub}_i\),显然 \(\text{sub}_i\) 代表的子串已经被计算过了。

加上 \([l,r]\) 的限制。问题就是遍历到的 \(q\) 内部最长子串并不一定被包含在 \([l,r]\) 中,可以想到维护 \(S\)\(\rm endpos\) 集合来解决这个问题,具体使用线段树来维护。首先,对于插入字符时产生的叶子节点,我们在对应线段树上插入字符下标;然后按 \(\text{parent tree}\) 向上线段树合并,这样每个点的线段树就是它对应的 \(\rm endpos\) 集了。

假设现在遍历到 \(q\),可以在它的 \(\rm endpos\) 集中二分出最大的右端点 \(x\) 且满足 \(x\leqslant R\),然后 check 一下 \(\rm endpos\) 集合中最短串的右端点若是 \(x\) 的话,左端点会不会超过 \(L\),如果不超过 \(L\),选择集合中最长的不超过 \(L\) 的串即可;反之,还需要不停跳 \(\text{parent tree}\).

复杂度是均摊正确的。你可能会对做法的正确性有疑问,事实上,如果前缀 \(t[1\dots i]\) 在某个节点不存在属于 \([l,r]\) 的串,那么 \(t[1\dots i+1]\) 也不可能在这个节点加上 \(t_{i+1}\) 转移到的节点中找到属于 \([l,r]\) 的串。

总结一下,把 \(T\) 放在 s-SAM 上跑相当于算公共子串(同时也给 \(S\) 去重),而在 t-SAM 上跑相当于给 \(T\) 去重。

后记:本来想要尽量讲得简单且易懂,现在看来语言表述能力可能还是有欠缺。这么一长段是不是也没人会认真看下去啊。突然感觉很感慨,放在以前这题自己是绝对会抄很久题解,交无数发的。现在竟然也可以理出做题思路,自己写 + debug 代码了。我作为 OIer 的寿命也快要终结了 =w=.

abc203f - Weed

题意简述:有 \(n\) 株草,第 \(i\) 株的高度为 \(a_i\),你可以预先拔掉不超过 \(k\) 株草,然后按如下方式操作,直到无法操作为止:

  • 选取没拔掉的草中最高的草(设其高度为 \(h\)),一次拔掉所有高度 \(\displaystyle >\left\lfloor \frac{h}{2}\right\rfloor\) 的草。

你需要在操作次数最少的情况下,最小化预先拔掉的草的数量。

\(1\leqslant n\leqslant 2\cdot 10^5,0\leqslant k\leqslant n,1\leqslant a_i\leqslant 10^9\).

一定要对 \(\displaystyle \left\lfloor \frac{h}{2}\right\rfloor\) 敏感啊!看见除以二想 \(\log\) 啊!可以发现操作次数至多为 \(\log a\),所以操作次数这个信息是可记录的,我们可以枚举操作次数,在此基础上最小化拔掉的草数量。

将草按高度升序排序,可以发现一次操作一定能砍掉一段区间,基于此可以设计 \(\tt dp\):记 \(dp(i,j)\) 为花费 \(j\) 次操作,已经拔掉前 \(i\) 株草的最小预先拔掉草数量。那么转移有

\[dp(i,j)=\min\{dp(i-1,j)+1,dp(p-1,j-1)\} \]

其中 \(p\) 是满足 \(a_p>\displaystyle \left\lfloor \frac{a_i}{2}\right\rfloor\)最左端 的草。总复杂度 \(\mathcal O(n\log a)\).

posted on 2020-06-19 11:13  Oxide  阅读(172)  评论(0)    收藏  举报