JSOI部分题解
JSOI2018
战争
问题转化为给定你两个凸包\(\mathbb S,\mathbb T\),每次独立的询问将\(\mathbb T\)中的每个点移动一个向量,问\(\mathbb S,\mathbb T'\)是否有交。
我们知道对于两个凸包\(\mathbb {A,B}\)的闵科夫斯基和为\(\mathbb C=\{\vec a\in\mathbb A,\vec b\in \mathbb B\;|\;\vec a+\vec b\}\),
而两个凸包对于一次移动向量\(\vec w\)有交,则存在\(\vec a=\vec b+\vec w\Leftrightarrow\vec w=\vec a-\vec b\)。
那么构造\(\mathbb Q=\{\vec t\in \mathbb T\;|\;-\vec t\}\),构造\(\mathbb P=\mathbb{S+Q}\),每次判断是否有\(\vec w\in\mathbb P\)即可。
列队
可以贪心地想,将\([l,r]\)内所有人的休息点从小到大排序后依次放入\(K...K+r-l\)答案是最优的。
那么现在问题主要转化为如何快速求\(\sum_{i\in [l,r]} |a_i-(K+i-l)|\)(假设\(a\)已排好序)。
这时候可以对于原序列\(\{a\}\)建主席树维护个数及\(a\)的和,考虑拆掉绝对值的话就是二分\(mid\),表示\(a\)大小前的\(mid\)名均有\(a_i\leq K+i-1\),因为\(a\)两两不同所以可以保证存在一个这样的分界点。
直接在外面二分后用等差数列求和算答案复杂度为\(O(n\log^2 n)\)可以获得\(70pts\),改为在主席树上二分复杂度\(O(n\log n)\)可获得满分。
JSOI2017
潜入行动
有一个显然的dp是设\(f[x][i][0/1][0/1]\)表示\(x\)的子树内安装了\(i\)个监听器,他自己不选/选,他父亲不选/选的方案数。
转移较为繁琐而且容易实现,这里不再赘述。
考虑复杂度:乍一看复杂度为\(O(nk^2)\)但是仔细思考发现满足度数为\(k\)的点最多\(\frac nk\)个,那么最终复杂度为\(O(nk)\)。
防御网络
题意:求从一个仙人球中任选一个点集所构成的斯坦纳树大小的期望。
考虑每条边的贡献,如果一条边不再环内的话贡献很好算。
那么主要问题就是解决环上的边怎么算贡献,只考虑某一个环,如果一个点的子树内选择了点的话就把环上这个点给标记出来,那么最后选择的东西就一定是整个环的长度减去相邻两个被选中的点的最大距离。
设\(f_x\)表示相邻两点最大长度不超过\(x\)的方案数,那么对于一个\(x\),它的方案数就是\(f_x-f_{x-1}\)。
因为是一个环,断环为链后枚举最左被选择边的点就可以消除原来环的影响。
剩下的部分考虑dp,设\(g_i\)表示当前在第\(i\)个点且强制选第\(i\)个点的方案数,转移时强制长度差不超过\(x\)前缀和优化即可。
最终复杂度\(O(n^3)\)。
绝地反击
这里提供两种方法:
方法一:
是我自己想到的,对于圆上点的排列,假设所有点均由正方向旋转度数\(\alpha\),那么最优解函数\(f(\alpha)\)一定为一个单峰函数。
三分\(\alpha\)后再二分时间\(t\),将到达时间\(\leq mid\)的我方舰队向敌方母舰连边,跑二分图匹配看是否有完美匹配即可。
这种做法我在loj上是\(80pts\),但是经过一些常数优化后应该是可以过的。
方法二:
二分时间\(t\),那么对于每艘战舰在圆弧上的交点至多只有\(2\)个,而对于旋转,可以发现本质不同的转法一定是有一个点转到了这\(2n\)个交点中的其中一个。
我们将这\(2n\)个转角极角排序(这\(2n\)个点可用余弦定理算出),则每次改变转角最多加入或删除一组匹配,手动模拟退流即可,复杂度\(O(二分图匹配\times\log n)\)。
JSOI2016
最佳团体
考虑01分数规划,那么我们现在二分了比值\(mid\),每个点有一个新的权值\(c_i=p_i-s_i\times mid\),
现在要求在满足条件的情况下使\(\sum c\)最大,树形背包即可。
独特的树叶
因为是树的同构问题,考虑树哈希。
有一种异或的树哈希方法(\(f\)为哈希数组):
\[ f_i=\bigoplus_{j\in son_i} f_{j}\times seed+size_j \]
通过换根可以求出以每个点为根的\(f\)值,将\(A,B\)树分别哈希并将\(A\)中的每个哈希值丢到set中,如果有\(B\)中有一个叶节点的父亲去掉(xor)对应叶节点的\(f\)值后这个哈希值不在这个set中,说明对应的叶节点就是那个多余的点。
扭动的回文串
单独存在于\(A,B\)串中间的回文串可以直接\(\text {manacher}\)求出,考虑“扭动”形成的回文串。
枚举回文中心,因为“扭动”的回文串,必然在\(A\)或\(B\)中对应有一个最长的回文串,这是\(\text{manacher}\)就已经求出来了的,再用二分+哈希把两串拼一起所形成的新串能够再拓展的最大长度弄出来即可。
灯塔
其实就是要你对于每一个\(i\)求出\(p_i=\lceil\max\limits_{j}(a_j-a_i+\sqrt{|i-j|})\rceil\)。
有一种做法就是对于每个\(i\),\(\sqrt{|i-j|}\)的取值不超过\(\sqrt n\)个,而且对于每个\(i\)和某个取值\(x\),所对应的\(j\)一定在一段或两端连续的区间中,可以用st表查询最大的\(a_j\),复杂度\(O(n\sqrt n)\)。
另外一种做法只考虑\(j的情况,之后通过\(\text{reverse}\)求出\(j>i\)的情况,而可以发现决策点具有决策单调性,用决策单调性优化可以做到\(O(n\log n)\)。
位运算
假设我们选出来的数\(A_1,A_2...A_N\)满足,\(A_0> A_1\geq A_2...\geq A_N\),其中为了方便我们令\(A_0=R\)。
考虑状压这\(N+1\)个数的大小关系,那么状态\(s\)有\(N\)位,每一位\(0/1\)表示\(A_i(>\text {or}\geq) A_{i+1}\),设\(f_{i,s}\)表示当前从高往低考虑到第\(i\)位大小关系为\(s\)的方案数,枚举当前位的填数情况\(t\)可以进行转移,而对于每个循环的转移时一样的,处理完一个循环的情况后可以矩阵快速幂求出方案数。
炸弹攻击
这题比较玄学,网上所查得到的大部分题解说是模拟退火实则爬山算法。
就直接按照随机化的方法\(\text{rand}\)一个移动向量看是否更优即可,温度、温度变化量、eps以及一些退火中的tricks网上都有,这里不再赘述。
飞机调度
首先可以想到\(\text{floyd}\)求出任意两点之间的最短路,因为存在维修时间所以要将\(dis_{i,j}\)设为\(g_{i,j}+p_j\)。
假设某一趟航班\(i\)从\(x_i\rightarrow y_i\),时间由\(s_i\rightarrow t_i(t_i=s_i+T_{x_i,y_i}+p_{y_i})\),那么对于航班\(j\),如果想让\(i,j\)共用一趟飞机则必须满足\(t_i+dis_{y_i,x_j}\leq s_j\)。
我们将\(i\rightarrow j\)连一条边,发现整张图一定是个DAG,直接跑最小路径覆盖即可。
无界单词
首先考虑第一问,设\(f_i\)表示长度为\(i\)的\(|border|=0\)的串的个数。
我们考虑容斥,减去\(|border|>0\)的情况,因为如果\(|border|\geq \lceil\frac i2\rceil\),那么可以减去中间公共部分变成\(<\lceil\frac i2\rceil\)的情况,所以有
\[ f_i=2^i-\sum_{j=1}^{\lfloor\frac i2\rfloor} f_j\times 2^{i-2j} \]
对于第二问考虑二分,则问题实际上变为求前缀为\(s\)时的\(f_i\)。
显然有\(f_i=[前i个字符无border],i\leq |s|\)。
对于\(i>|s|\),则分类讨论之:
首先有
\[ f_i=2^{i-|s|}-\sum_{j=1}^{\lfloor\frac i2\rfloor}f_j\times c_{i,j} \]
其中\(c_{i,j}\)表示系数,有:
\[ c_{i,j}= \begin{aligned} \begin{cases} 2^{i-2j}&j\geq |s|\\ 2^{i-|s|-j}&j+|s|\leq i\\ [s有长度为j+|s|-i的border]& \text{otherwise} \end{cases} \end{aligned} \]
然后按照这种方法转移就好了。
轻重路径
首先可以用树状数组单点加、区间查询维护每个点的\(size\)。
考虑这一次我们删掉了叶子\(x\),那么对于\(x\)到根\(rt\)的路径,如果要满足上面的一个点\(u\)它要改变他由重变轻的话必有\(size_u\leq \frac {size_{rt}}2\),我们可以二分这个点,那么这样的话最多二分\(O(\log n)\)次。
判定一条边是否从重边变成轻边的依据是父亲的重儿子之前指向\(u\),同时删除节点后有 \(size_u+1=size_{another\_son}\),注意特判\(u\)是父亲子树最后一个节点的情况。
复杂度\(O(n\log ^3n)\)但是树状数组以及树剖、二分的常数都比较小,还有这题的思路感觉比较类似于CSP2019树的重心。
病毒感染
题目的意思是如果往左走就要把之前左边没治愈的治愈完。
那么整个过程可以分为若干个子段,每个子段治完子段中的所有村庄然后再回到该子段的起点继续治接下来的子段。
设\(f_i\)表示目前在\(i\)且\(1...i\)均治愈完毕的最小代价,转移的话枚举这个子段的起点:
\[ f_i=\min\limits_{j
其中\(s\)为前缀和\(g_{i,j}\)为\(i\)走到\(j\)再回到\(i\)所花费的最小代价。
考虑\(g_{i,j}\)由\(g_{i+1,j}\)转移过来,枚举\(i\)在不在当时治愈有:
\[ g_{i,j}=g_{i+1,j}+\min\begin{cases}3a_i(j-i)+(s_n-s_i)+2(s_n-s_j)\\2(s_n-s_i)+(s_n-s_j)\end{cases} \]
然后就可以dp了。
反质数序列
考虑到奇数和奇数、偶数和偶数之间不可能为质数,那么所有元素就构成了一个二分图。
其中奇、偶之间如果是质数的话就连一条边,答案就是最大独立集也就是\(|\mathbb V|-\)最大匹配,注意\(1\)选的个数不能超过\(1\),所以\(1\)只要保留一个。
炸弹攻击2
考虑枚举每一个发射源,算出每个发射源的贡献。
将这个发射源作为原点,将其他除了发射源之外的点放一起极角排序,因为题目保证所有敌人都在己方单位上面,所以答案就是两个极角不超过\(\pi\)的激光塔之间所夹的敌人数,又因为这题实际上是个环的结构,所以需要断环为链+前缀和维护。