[合辑]杂题题解汇总
没时间写代码了,以口胡换代码了。
「GXOI / GZOI2019」旅行者
多源点最短路。
一种方法是,注意到两个点不同,说明他们的二进制数至少一位不同,那么可以按照二进制,每次考虑二进制的一位,将这一位为 \(1\) 的所有点当成起点跑最段路。这种方法的复杂度是 \(\mathcal O(n\log^2 n)\) 的。
「SDOI2019」热闹的聚会与尴尬的聚会
找到 \(\max p\) 是经典原题,每次将度数最小的点删掉,考虑剩下的点的导出子图。
找到 \(\max q\) 就是 NP 问题了(最大团问题),不过由于题目的限制很松(满足 \((p+1)(q+1)<n\) 即可),所以一种可以被证明正确的做法是每次在剩下的可选点中选择度数最小的点。
当然,如果没有思路,也可以模拟退火来做,毕竟这个上界很松嘛。
「LibreOJ NOI Round #1」失控的未来交通工具
注意到 \(u\to v\) 经过的边要走奇数次,而其他边都是走偶数次,当然,环也可以走奇数次。也就是说,其实真正对路径长度有贡献的,只有环的长度和所有边长度的两倍,还有最基础的两点之间的距离,因此,我们只需要关注所有的环长 \(a_1,a_2\cdots\) 和边长 \(b_1,b_2,\cdots\) 即可(当然,我们也不用关注每一个环,只要把所有在环上的边都考虑到就行)。
根据经典剩余系的结论,一堆数随便加在 \(\bmod m\) 下的循环节为 \(\displaystyle \frac{m}{\gcd(m,a_1,a_2,\cdots,2b_1,2b_2,\cdots)}\),也就是说每 \(g=\gcd(m,a_1,a_2,\cdots,2b_1,2b_2,\cdots)\) 就有一个数可以被取到。
相当于最后就是求方程 \(d+pg\equiv x+qb\pmod m(q\in [0,c-1])\) 的非负整数解数量,其中 \(d\) 为 \(u,v\) 两点之间的距离,但是我们不用解这个,可以解出 \(d\equiv x+qb\pmod g\) 的最小非负解 \(q_0\),每次将这个特解扩大 \(\dfrac{\gcd(a_1,a_2,\cdots,2b_1,2b_2,\cdots)}{\gcd(a_1,a_2,\cdots,2b_1,2b_2,\cdots,m)}\) 即可。
异或最短路也是类似的思路。
「PKUWC2018」Minimax
先考虑一个暴力的 DP,设 \(f(u,j)\) 表示点 \(u\) 成为所有值中第 \(j\) 大的那个的概率是多少,转移的时候发现是一个和前后缀和有关的形式,使用线段树合并即可。
「JSOI2018」潜入行动
我是傻逼,刚开始读错题了,还以为监控可以监视所有与 \(u\) 有一定距离内的点,结果就只有 \(N(u)\) 啊,那没事了。
如果你没有读错题,你会发现转移只需要关注它和它儿子的监控与被监视状态,因此设计转移 \(f(u,k,0/1,0/1)\) 表示当前点为 \(u\),其子树内有 \(k\) 个监控,它是否安装监控,它是否被监控的方案数,转移就很朴素了。
复杂度是树背包的复杂度,\(\mathcal O(nk)\),稍带些常数。
「HNOI2014」世界树
一道虚树题。
对关键点集建出虚树,然后用换根 DP 求出虚树上每个点求出其管辖点(本来想叫支配点的),然后对于虚树上的每条边,考虑它的两个端点的分配方案:
- 如果属于相同管辖点,那么直接加到管辖点头上;
- 如果分属不同管辖点,用二分找到中间的分界点;
就这么简单?不是的,我们需要考虑的不只是虚树上的点,还有非虚树的点,即我们建的虚树的每个点的贡献并非简单的 \(1\),还要包含它的子树中不在虚树上的点的数量,算贡献的时候要将这个部分也算上,因此我们建立虚树的过程和传统过程稍有不同,要使用树剖建树,建树的复杂度是 \(\mathcal O(n\log^2 n)\) 的,处理询问的复杂度是 \(\mathcal O(n)\sim \mathcal O(n\log n)\) 的。
「APIO2014」序列分割
有意思的是,最后的价值和分割顺序没有关系。
先考虑简单的情况,分成三块,假设为他们的大小分别为 \(a,b,c\),显然有两种分割方案:
- \((a+b)\times c+ab=ab+ac+bc\);
- \(a\times (b+c)+bc=ab+ac+bc\);
可以推广到更多块的情况,此时原题就变成了一个斜率优化的板子,注意需要滚动一下,不然空间不够用。
「SDOI2016」生成魔咒
可能是那个时候 SAM 并不常见吧,这题就 SAM 板题(我用 SA 打了半天还没跳出来,SA 差评 😦 )
「NOI2015」寿司晚宴
小于 \(\sqrt{500}\) 的质数只有 \(8\) 个,可以把他们状压起来,对于较大的质数,将拥有同一个大质数的数放到一起 DP,那么,在这一段中,要么只有集合 A/B 选这段数中的数,要么都不选这段的数。
「CTSC2017」网络
能猜到结论,后面的还不大会,先咕着。
「AHOI2013」差异
是那个时候 SAM 还不普及吧,就一 SAM 板题。
「BZOJ2407」探险
我是傻逼,我是怎么想到网络流那边去的,最小循环费用流......
需要去发现的是,当我们走出第一步后,这个问题就变成一个裸的最短路问题,此时我们要求的是:从 \(1\) 走了一步之后,假设走到 \(u\),那么从 \(u\) 走回到 \(1\) 而不再经过 \(u\to 1\) 的最短路,也就是说,我们要从 \(N(1)\) 中选择两个点 \(u,v\),算出 \(1\to u\to v\to 1\) 的最短路,这不就是多源点最短路?!!因此,同样可以采用二进制分组的方法来做,复杂度 \(\mathcal O(n\log^2 n)\).
还有重构图的方案,就算了。
「SCOI2008」天平
塌馬の,又假了。
祂媽鍀,犹没假。
我的思路:对于 =
,连双向边,对于 </>
,连有向边,对于 ?
不管它,跑完缩点之后变成多个 DAG,并且每个部分最多有一条长度为 \(3\) 的链(多条可合并),但是我忘记了即使是 ?
它们之间也有关联,不能忽略。于是我以为它假了。
后来想想好像也没假,因为建出这个 DAG 图后,我可以得出每个砝码的取值,反正取值只有 \(1,2,3\) 三种。然后,我就可以暴力 \(\mathcal O(n^2)\) 匹配算答案就行了。复杂度可能是 \(\mathcal O(n^2)\) 的吧。
刚开始以为它有局限,因为砝码只有 \(1,2,3\) 三种取值,后来发现它并没有这种限制,因为无论如何,我可以用 \(\mathcal O(n)\) 处理出每个砝码的取值上下界,唯一需要注意的一点是,枚举的两个砝码可能互相也有限制,要注意判断它们之间的限制是否满足。
另一种方法:为什么我想不到差分约束上面去啊😢,这么明显了,我们只知道两砝码之间的大小关系啊......
根据限制建出差分约束(注意,为 ?
也是可以建出来的),然后处理最长路和最短路(因为要判断是否结果唯一),然后将 \(a+b>c+d\) 变成 \(a-c>d-b\),枚举 \(c,d\) 的砝码判断就行了。
由于有负权变,所以只能使用 Floyd 或者 SPFA,复杂度为 \(\mathcal O(n^3)/\mathcal O(nm)\),同阶。
但是差分约束有它的好处 —— 不同讨论那么多东西。
「CTSC2012」熟悉的文章
想了个 \(\mathcal O(n\log^2 n)\) 的做法就润了,看题解发现咋都是 \(\mathcal O(n\log n)\) 的啊......后来发现数据范围是 \(10^6\) 论小学数数的重要性,去掉一个 \(\log\) 很简单,因为你能想到的那个 DP 是可以用单调队列优化的,因为 \(L(i)\)(\(i\) 开始最多能往前面匹配的那个位置)显然是不降的。
「中山市选」杀人游戏
|真理報|
头条
因遭家长举报引诱未成年人犯罪
信息学竞赛或遭教育部集体封杀据记者报道,因著名市级地区中山市举办信息学竞赛遭到家长举报引诱未成年人犯罪,教育部已发布通知,禁止各地举办类似信息学竞赛的各种赛事,包括但不限于 CSP,NOIP,省选,NOI,WC,APIO.
记者采访了一位参加该竞赛的学生,沃潮溺,的母亲。
记者:“您是怎么认为信息学竞赛引诱未成年人犯罪这一事件的呢?您认为它会对您的孩子产生怎样的影响?”
潮溺妈:“这件事情没有商量的余地,这样正规的竞赛居然有这么血腥的题目,杀人游戏!杀人都在那么大的题目标题上写着了,还说杀人是游戏,如此正规的选拔都存在这种血腥暴力的倾向,很难不相信,在其他的一些什么比赛里面,也给我的孩子灌输血腥暴力恐怖的思想。我真的很担心,我已经参加三年竞赛的孩子沃潮溺现在的心智是否正常,他会不会突然像标题里面,将杀人当做游戏。这种竞赛应该早点禁止,不对,是被封杀,不能有任何一点苗头。”
上述内容纯属虚构
建图,跑完 tarjan 之后得到了一个 DAG,对于这个 DAG,显然我们只需要向所有入度为 \(0\) 的大点的其中一个发起询问即可,此时不被干掉的概率为 \(1-\dfrac{c}{n}\),其中 \(c\) 是入度为 \(0\) 的点数量。
但是还有一种情况:如果存在一个入度为 \(0\) 的连通分量,它的大小为 \(1\) 且它的邻接点的度数都至少为 \(2\),那么,我们不需要询问它就可以确定其他的所有点了。
因此,至少存在上面那种特殊点至少一个,答案就会变成 \(1-\dfrac{c-1}{n}\) 所谓排除法
「ZJOI2012」灾难
思路很明显,建出这个 DAG 的支配树,每个点的答案就是其子树大小减去 \(1\).
当然可以直接使用支配树,不过我已经完全忘记怎么打了不会支配树。不过这个题很特殊诶 —— 它是个 DAG,一个 DAG 的支配树还不好求吗?
一个点的支配祖先就是它在 DAG 上的所有前驱的支配点的交集(以及它自己)。什么鬼范围啊这,\(n\le 2^{16}\),我直接一发 bitset
跑路了......不过空间存不下。
踏嫲锝,按照拓扑正序遍历这个图,每个点的最近支配点就是反图上它的所有出点在树上的 LCA,处理一下就好了。
「NOI2018」你的名字
为什么我的第一反应是 「あなたの名前」
给一个串串 \(A\),每次的询问给你一个区间 \([l,r]\) 和另外一个串串 \(B\),问你串串 \(B\) 的所有本质不同的子串串中,不是 \(A[l:r]\) 的子串串的数量。
对串串 \(A\) 建出 SAM 之后用线段树合并维护每个点的 \(\rm endpos\) 集合。
正难则反,考虑用所有本质不同的子串串减去被包含的本质不同的子串串数量,现在的问题就变成,\(A[l:r]\) 和 \(B\) 的本质不同公共子串串数量。
按照 \(B\) 在 SAM 上走,走到每个等价类 \(u\) 时,有一个在 \(B\) 上的最长匹配长度 \(len\),我们问一下 \(u\) 的 \(\rm endpos\) 中 \([l+len-1:r]\) 是否有点即可,如果真的有,就说明 匹配成功,将答案减去 \(l\) ?不对,并不是 \(l\),我们应当减去本质不同的串的数量,直接减去 \(l\) 就会多减一些东西。假设当前后缀为 \(B[1:i]\),那么我们应当减去 \(l-falen(i)\),其中 \(falen(i)\) 表示 \(i\) 后缀在 \(B\) 的 SAM 上对应节点的父节点的 \(mxlen\).