JOISC 2020 简要题解
2020 真的是难度天花板啊啊啊啊啊啊啊啊啊。
咱就说比赛的平均码量是不是大了点呢
发现很多题目缺少的是第一步的转化,这种转化要多积累。
「JOISC 2020 Day1」建筑装饰 4
- 给定长度为 \(2n\) 的序列 \(A,B\),构造序列 \(C\),用
AB序列表示,若第 \(i\) 位为A表示 \(C_i=A_i\),反之同理。 - 要求恰好有 \(n\) 个
A,且序列单调不降。 - \(n\leq 5\times 10^5\)。
设 \(f(i,j,0/1)\) 表示考虑了前 \(i\) 个数,已经填了 \(j\) 个 A,且上一次填的是 A 或 B 是否可行。直接转移就有 \(O(n^2)\) 的做法了。
可以归纳证明,对于同一个 \(f_{i,0/1}\),合法的 \(j\) 是一段区间,具体的:
设 \(l_{i,0/1},r_{i,0/1}\) 为对应的合法区间。
归纳的初始条件,\(l_{1,0}=r_{1,0}=1,l_{1,1}=r_{1,1}=0\),就是看第一步是选
A还是B,都是合法的。之后对于 \(i>1\),设 \(a=l_{i-1,0},b=r_{i-1,0},c=l_{i-1,1},d=r_{i-1,1}\)。
对于 \(l_{i,0},r_{i,0}\),初始的合法 \(j\) 是 \(s=\varnothing\):
- 若 \(A_i\geq A_{i-1}\),\(s\gets s\cup [a+1,b+1]\)。
- 若 \(A_i\geq B_{i-1}\),\(s\gets s\cup [c+1,d+1]\)。
对于 \(l_{i,1},r_{i,1}\) 是类似的,设初始集合为 \(t=\varnothing\):
- 若 \(B_i\geq A_{i-1}\),\(t\gets t\cup [a,b]\)。
- 若 \(B_i\geq B_{i-1}\),\(t\gets t\cup [c,d]\)。
这就比较明显了,每次合法的 \(j\) 的集合都是至多两个区间的并集。
并且同时也能归纳证明,\([a,b],[c,d]\) 这两个区间的并集仍然是一个区间,首先对于 \(i=1\) 是成立的。
假设 \(A_{i-1}\leq B_{i-1}\),那么:
- \(s\) 只可能是:\(\varnothing,[a+1,b+1],[\min(a+1,c+1),\max(b+1,d+1)]\)。
- \(t\) 只可能是:\(\varnothing,[a,b],[\min(a,c),\max(b,d)]\)。
这几个区间的 \(3\times 3\) 的任意组合都是满足条件的。
那么根据上面的归纳过程处理出 \(l,r\) 数组,之后直接从后往前倒推即可。
「JOISC 2020 Day1」汉堡肉
- 给定平面内 \(n\) 个矩形,求出 \(k\) 个点,使得所有矩形至少包含一个点,保证有解。
- \(n\leq 2\times 10^5,k\leq 4\),坐标值域 \(10^9\)。
随机化可过,厉害了。
对于 \(k\leq 4\) 感觉就是乱搞,所以就写了个 shuffle 然后贪心,就是尽量一段连续矩形取交,T 飞了。
然后看题解发现确实很多随机化,一看发现是 面积减少量最小/减小比例最小,是我年轻了(
口胡正解。首先,如果所有矩形均有交,那么任意取点即可。
如果存在 \(\max(l)\leq \min(r)\),或 \(\max(d)\leq \min(u)\),对应一维算是废了,直接变为一维的简单情况。
否则,一定有 \(\max(l)>\min(r)\) 且 \(\max(d)>\min(u)\)。
显然最优情况这四条线围成的矩形的每条边都得有点(可以是端点)。
例如 \(\max(l)\) 往右一定需要有点,但是如果不在这条线上就不如向左平移到它上面来,因为它是最右的左边界。其它方向同理。
对于 \(k<4\),肯定需要有点在端点,直接搜索,每次枚举端点,然后删去被覆盖的矩形,再递归到 \(k-1\) 的情况,复杂度 \(O(4^kn)\)。
对于 \(k=4\),对其它矩形分类讨论,看它和这四条关键边:
- 仅和一边有交:等价于限制这条边上的点必须在这个区间中。
- 和 \(\geq 3\) 边有交:显然会包含完整的至少一条边,一定合法,可以不管。
- 和 \(2\) 边有交:相当于一个 2-sat。
将涉及到的区间处理出来,如果同一条边上两个区间不相交说明只能选一个,对着这 \(O(n)\) 个区间使用线段树优化建图 2-sat 即可。
口胡是快乐的。
「JOISC 2020 Day1」扫除
- 给定等腰直角三角形,它是由 \(x\in[0,n],y\in[0,n],x+y\leq n\) 的点构成的。
- 初始内部有 \(m\) 个点,\(q\) 次询问,支持 \(4\) 种操作:
- 查询点 \(i\) 的坐标。
- \(\forall(x, y)\and x\leq l,y\gets \max(y,n-l)\)。
- \(\forall(x,y)\and y\leq l,x\gets \max(x,n-l)\)。
- 新增一个点在坐标 \((x,y)\)。
- \(n\leq 10^9,m\leq 5\times 10^5,q\leq 10^6\)。
神神神的大 DS。
一定要看部分分,对于难题,往往部分分有强烈提示性。
对于初始 \(x_i\geq x_{i+1},y_i\leq y_{i+1}\) 且没有加点操作,发现所有点一定均保持这样,相对顺序不变。
此时每次操作影响的是一段区间,很好维护。
更普通的,对于没有加点操作的情况,可以对于每个点预处理找到第一个影响到它的操作,这是一个简单的二维偏序问题。
只要一个点被操作过,那就和其它被操作过的点一同,具有了先前的性质,支持加点用平衡树维护即可。
最后对于加点操作,因为新加入的点没有经过之前所有操作,所以不具有只要被影响一次就能加入平衡树的性质。
这时考虑每次询问,相当于查询初始给定一个点,在某段操作区间的操作下得到的点。
考虑线段树分治,此时线段树节点上的每个询问都会被这个线段树节点代表的所有操作影响,所以可以仿照上述做法直接做。
总复杂度是 \(O(n\log^2 n)\)。
「JOISC 2020 Day2」变色龙之恋
- 交互题。
- 给定 \(2n\) 只变色龙,其中颜色为 \(i\in[1,n]\) 的各恰好有 \(2\) 只,性别为 X 和 Y 的变色龙分别 \(n\) 只,同性别的变色龙一定不同色。
- 每只变色龙都有唯一一只异性且异色的变色龙作为恋爱对象,且不存在两只变色龙同时追求一只变色龙。
- 每次询问你可以询问一个点集 \(s\),如果 \(x\in s\),那么若 \(x\) 的恋爱对象 \(y\in s\),那么 \(x\) 此时的肤色为 \(y\) 的原色,否则为 \(x\) 的原色。
- 交互库会回答此时不同颜色种类数。
- 用 \(\leq 20000\) 次询问确定 \(n(n\leq 500)\) 对异性同色对。
虽然做了很多 JOISC 的交互题,但这道题真的让人眼前一亮。
比较难动手的时候,考虑笨拙一点的操作,只问两个点 \((a,b)\),当且仅当:
- \(a,b\) 同色。
- \(a\to b\) 且 \(b\not \to a\)。
- \(b\to a\) 且 \(a\not \to b\)。
这三者其一时,颜色种类数为 \(1\)。如果存在这种关系就连无向边 \((a,b)\),那么每个点的度数是 \(1\) 或 \(3\),且只有互连的情况会是 \(1\)。
如果度数为 \(1\) 答案就确定了,否则可以 \(\binom{3}{2}\) 的选两个点和 \(i\) 一起询问,只有没选 \(a\to b\) 的时候答案为 \(2\)。
于是就可以确定从 \(a\) 出发的指向边,如此每个都确定了,剩下没确定的就是同色边。
所以如果连出了上面的边,大概 \(O(3n)\) 就能得到答案。
找边可以用常规方法:二分。因为如果有集合 \(S\),其内部无边,那么当且仅当 \(\text{Query}(S\cup \{a\}) \neq |S|+1\) 时 \(a\) 同 \(S\) 内部有边。
那前提是有这个内部无边的集合,于是我们想确定这个二分图的形态。
但是我们做不到,但是这不重要,可以 \(1\sim 2n\) 扫一遍,每次维护 \([1,i]\) 的连边。
既然这些边已经确定了,那么一定可以二分图染色,并令 \(i+1\) 在这两个集合中分别二分。
这两个集合不一定真的是二分图的集合,因为互连的边体现不出来,但是不要紧,并不影响。
于是大概 \(O(2n\log n+6n)\) 解决了这道题,后面的 \(6n\) 是夸大化的试探所用次数估计,可以发现本题的限制比较松。
「JOISC 2020 Day2」有趣的 Joitter 交友
- 给定 \(n\) 个点,初始无边的有向图。\(m\) 次询问,每次连有向边 \(a\to b\)。
- 任意时刻,如果存在三元组 \((x,y,z)\),满足有边 \(x\to y,y\to z,z\to y\),那么连边 \(z\to x\)。
- 每次询问求按照上述操作后图中边的条数。
- \(n\leq 10^5,m\leq 3\times 10^5\)。
实现难度远高于思维难度。
对于每个团缩到一起,如果一个点 \(x\) 有边连向团 \(A\) 中的某个点 \(y\),那么 \(x\) 会向团 \(A\) 的每个点连有向边。
同时如果两个团互相有边,那么就能缩成新的团。
然后就拿一个 map 两个 set 启发式合并一下,分别维护 #$#……@&@^@#&* 就好了。
「JOISC 2020 Day2」遗迹
- 对于初始有 \(1\sim n\) 各两个的长度为 \(2n\) 的序列,进行 \(n\) 轮如下操作:
- 对于每种存在两个的数字,将下标较小的 \(-1\)。
- 不难发现最终一定有 \(n\) 个 \(0\) 和 \(1\sim n\) 各一个。现给出最终有值的位置下标,计数可能的初始序列个数。
- \(n\leq 600\)。
神题。比较难入手,首先考虑,如果给出初始序列,怎么用对计数有帮助的方式得到原序列:
for(int i = 2 * n; i >= 1; i --) {
while(a[i] && vis[a[i]]) a[i] --;
vis[a[i]] = true;
}
这样就得到了最终序列,同时也能够设计一个状态:\(f(i,s)\) 表示从 \(2n\) 开始,考虑到了第 \(i\) 位,\(\text{vis}\) 数组是 \(s\) 的方案数。
但是发现已有状态不太支持转移,但是已经有了状压了还加状态对正解可能毫无用处。
所以突发奇想可以令两个相同的数字本质不同,然后最终方案 \(/2^n\) 才是真正的答案,这样很方便转移。
转移分两种:
-
这次加的数没有使 \(\text{vis}\) 改变:
设 \(s\) 的极长 \(1\) 串前缀长度为 \(j\),那么显然当前数字只能在这里面选。
本来这个区间中的数有 \(2j\) 个(每个拆成两个),但是前面已经有了 \(j\) 个,但仅仅是这样吗?
根据已有信息,可以计算得到 \(\text{Break}\) 表示 \(i\sim 2n\) 中有多少个最终没有值的位,它们显然也都取值到了 \([1,j]\)。
这就是拆两位的原因,如果仅仅用数字种类数算,根本不知道有多少数位没被取过 \(2\) 次。
\[f(i,s)\gets f(i+1,s)\times (j-\text{Break}) \] -
这次加入的改变了 \(\text{vis}\)。
枚举 \(0\to 1\) 的那一位 \(k\),设它后边极长 \(1\) 串长度为 \(l\),那么显然它能取的就是 \(2+l\)(这一位 \(2\) 种,后面 \(l\) 种)。
这也是基于非前缀极长 \(1\) 串一定是没有 \(0\) 的这一事实,也即区间长度 = 区间中数的个数。
\[f(i,s\cup\{k\})\gets f(i+1,s)\times (2+l) \]
看上去很厉害,已经得到了 \(O(n^22^n)\) 的算法,可惜它甚至不是多项式时间。
显然要从状态上动手,极力压缩状态。
突发奇想,设 \(f(i,j)\) 表示考虑了 \(i\sim 2n\) 位,极长前缀 \(1\) 串长度为 \(j\) 的“方案数”。
“方案数”打上引号,是因为这不是真正意义上的方案数,有一种代价延后计算的意味,具体见后。
首先,显然这种状态设计对于第一种转移并没有影响。
对于第二种,如果 \(0\to 1\) 的不是 \(j+1\),那么状态不会改变,不考虑系数,直接转移:
然后考虑 \(j+1\) 变为 \(1\) 时将前缀 \(1\) 串变长,枚举 \(k\) 表示 \([j+1,j+k]\) 是极长第二段 \(1\) 串,注意是包含了 \(j+1\) 的。
在这里才考虑这一段 \(1\) 的方案数,首先确定哪次转移产生,只能从已确定位中选。
和 \(\text{Break}\) 相对应的有 \(\text{Protect}\),这是已有信息,应当从 \(\text{Protect}-j\) 中选 \(k-1\) 个。
然后是顺序,设 \(g_i\) 表示 \(i\) 个数值填充长度为 \(i\) 的对应区间,每个位置操作时均有值的方案数,那么有:
那个 \(k+1\) 是先前讨论的,第 \(j+1\) 位选择的方案数,因为这里的 \(k\) 包含了 \(j+1\),所以是 \(k+1\)。
唯一问题是求出 \(g_i\),发现如果从小往大填,因为每放的一位都需要有值,所以等价于 \(\forall i\in[1,n],\left (\displaystyle \sum \text{cnt}_i\right)\leq i\)。
设 \(h(i,j)\) 表示用 \([1,i]\) 填充了 \([1,j]\) 位的方案数,根据定义 \(g_i=h(i,i)\)。转移比较简单:
分别表示放 \(0/1/2\) 个该数值,时刻保证 \(i\geq j\) 即可。
「JOISC 2020 Day3」星座 3
- 给定 \(n\times n\) 的星空图,画面里有白色的大楼,黄色的星星,黑色的夜空。
- 第 \(i\) 列从最下方起数 \(a_i\) 行都是白色的大楼,有 \(m\) 颗星星,第 \(j\) 颗在 \((x_j,y_j)\),除此之外都是黑色的夜空。
- 若一个矩形满足:不包含白色格子且存在至少两颗星星,那么称之为一个星座。
- 你可以花费 \(c_j\) 的代价将第 \(j\) 颗星星删掉涂黑,求使得画面中没有星座的最小代价。
- \(n,m\leq 2\times 10^5\)。
感觉上不太难,但是自己想不到的题。
首先,一个重要的充要转化,题目要求等价于最大化留下的星星数,使得 \(\forall[l,r],\left(\displaystyle \sum_{x_i\in[l,r]} [y_i>\max_{j\in[l,r]} a_j]\right) \leq 1\)。
然后大概能想到建立笛卡尔树,然后直接设 \(f(u,i)\) 表示以 \(u\) 为根的子树,保留最大高度星星为 \(i\) 的最大收益。
设当前在点 \(p\),要合并子树 \(x,y\),转移遵循 \(> a_p\) 的只有一个的宗旨,分类讨论:
-
仅一个子树中有 \(>a_p\) 的:设
\[\text{xmax}=\displaystyle \max_{i\in [1,a_p]} f(x,i)\\ \text{ymax}=\displaystyle \max_{i\in [1,a_p]} f(y,i) \]那么直接
\[\forall i\in[a_p+1,n], f(p,i)\gets f(y,i) + \text{xmax}\\ \forall i\in[a_p+1,n], f(p,i)\gets f(x,i) + \text{ymax} \] -
两个子树中均没有,这个比较难具体表达,因为每一位都要找比它小的最大的值转移。
但实际上不需要精细到每一位,因为之后的每一步转移都是取前缀 \(\max\),而且这个前缀越来越长(后面的 \(a_p\) 越来越大)。
所以直接在 \(a_p\) 处记录 \(\text{xmax} + \text{ymax}\) 当转移即可。
这些转移都一脸线段树合并的样子,第一次知道线段树合并打 tag 也这么方便(
还有另一种解题方法。
对于每颗星星,从它所在横坐标开始跳,跳到第一个的 \(a_{\text{fa}} > y\) 的点。
那么选择了它这条 祖先-儿子 链就再不能被覆盖了,相当于是求选择树上最大权不相交链。
这是经典问题,可以用树剖 + DP 解决,大概就是 \(f(i)\) 表示以 \(i\) 为根的子树的答案,然后每次转移是个毛毛虫。
求的是不在链上但 \(\text{fa}\) 在链上的点的 \(f\) 的和,可以在每个点维护 \(s\) 表示所有直接儿子的 \(f\) 的和。
那么求的就是链上 \(s\) 和减去链上 \(f\) 和,这是树剖可以轻易维护的。
「JOISC 2020 Day3」收获
- \(n\) 个人,\(m\) 棵苹果树,在长度为 \(L\) 的环上,每个人顺时针每单位时间走一个单位长度。
- 初始所有苹果树均成熟,如果一个人到达一棵苹果树时它是成熟的,那么会采摘得到一个苹果。
- 苹果被采摘后 \(C\) 个单位时间才会重新成熟。\(q\) 次询问给出 \((i,T)\),问第 \(i\) 个人在 \(T\) 秒后摘了几个苹果。
- \(n,m,q\leq 2\times 10^5,n+m\leq L\leq 10^9,C\leq 10^9,T\leq 10^{18}\)。
好难啊~
一个人 \(i\) 摘了某个苹果树后,后面第一个能摘它的人是确定的,设为 \(p_i\),那么连边 \(i\to p_i\),边权为间隔时间。
一个苹果 \(i\) 会第一个被哪个人摘也是确定的,设为 \(q_i\),那么连边 \(i\to q_i\),边权为第一次采摘的时间。
那么,不难发现这是棵内向基环树,且叶子均为苹果。
将询问离线,对于树上点的询问,就是看子树内满足条件的苹果个数,简单二维数点。
对于环上的点,需要大力讨论一下,将一个苹果 \(i\) 表示为 \((\text{pos}_i,\text{dis}_i)\),分别为它第一次在环上出现的位置和时间。
那么之后它会在环上一直跑,设环长成这样:\(a_1\to a_2\to \cdots \to a_n\to a_1\),且有边权前缀和 \(d_i\) 和总长 \(\text{len}\)。
讨论询问 \((i,T)\) 被 \(\text{pos}=j\) 的苹果贡献到的量:
-
若 \(j\leq i\),那么有贡献:
\[\max(0, \left\lfloor \frac{T-(\text{dis}+d_i-d_j)}{\text{len}} \right\rfloor+1) \]处理这种问题典型(但我从未见过)的套路是,拆贡献 + 取模讨论。
即变为:
\[\max(0, \left\lfloor \frac{(T+d_i)-(\text{dis}-d_j)}{\text{len}} \right\rfloor+1) \]然后令 \(u_i=T+d_i,v_j=\text{dis}-d_j\),分别是人和苹果的“权值标志”。
设 \(p_i=\left\lfloor\frac{u_i}{\text{len}}\right\rfloor,q_i=u_i\bmod \text{len}\),\(p_j,q_j\) 对应 \(v_j\) 的,那么贡献就变为:
\[\max(0, \left\lfloor \frac{\text{len}(p_i-p_j)+(q_i-q_j)}{\text{len}}\right\rfloor +1) = \max((p_i-p_j)+[q_i\geq q_j], 0) \]那就是统计 \(p_i\geq p_j\) 的 \(p_j\) 的和,\(p_j\) 的个数,以及 \(q_i\geq q_j\) 的个数,前两个是一维数点,后一个是二维数点。
-
若 \(j>i\),那么有贡献:
\[\max(0, \left\lfloor \frac{T-(\text{dis}+d_i+\text{len} - d_j)}{\text{len}} \right\rfloor+1) \]不难发现就是上面的贡献 \(-1\),于是完全可以和上面混着统计,最后减去。
减去的量就是 \(i<j\) 且 \(p_i> p_j\) 或 \(p_i=p_j\and q_i\geq q_j\) 的量,拆开来又是两小只二维数点。
于是你对每个连通的基环树疯狂数点就没了。代码谁爱写谁写
其实如果考场上遇到这道题,能想到基环树建图的话后面写起来应该还是挺顺的。
「JOISC 2020 Day4」首都城市
- 给定树上每个点所属的城市,要求选则尽量少的城市,使得这些城市所有归属节点的并为一个树上连通块。
- \(n\leq 2\times 10^5\)。
自己做出来还挺有成就感的(
主要思路来源于链的部分分。发现可以分治做,每次钦定 \(\text{mid}\) 所属城市为连通块中必选的城市。
因为跨过分治中心的点必须选它,也就必须选它所属的城市。然后实现一个 expand 函数不断扩展。
每个城市只会被扩展一次,每次扩展枚举城市中的所有点,并把该点到 \(\text{mid}\) 的区间内的点都选择上,这是题意使然。
一个奇妙的设定是单点取消的限制,大概就是如果一种城市的点跨过了当前分治中心,那么就把它取消掉。
它之后显然不可能作为答案决策了,而 expand 合法的充要也恰恰是不会 expand 到被取消的点。
把链转到树上实际上更简单,直接点分治,然后每次强制选根,类似上面的 expand 过程即可。
实际上链到树的转换还一时糊涂,以为是钦定某个直接儿子为决策,然后想了半天以为树上不可做,emm。
然后才发现有个根是必选的,emm。
还有一种解法。
如果颜色 \(j\) 在颜色为 \(i\) 的节点的虚树上,那么连边颜色 \(i\to j\)。
倍增/线段树优化建图 + 缩点后,选择出度为 \(0\) 且节点总数最少的强联通分量即可,感觉上没有点分治优美。
「JOISC 2020 Day4」传奇团子师傅
提交答案题。退火就完了。那个可视化还蛮有意思的。
「JOISC 2020 Day4」治疗计划
- 疫情中有 \(n\) 个人,一开始都被感染,每天开始时,已感染者会传染给相邻未感染者。
- 每种治疗计划可用 \((t,l,r,c)\) 表示,意为在 \(t\) 天结束时,花费 \(c\) 的代价治疗 \([l,r]\) 的人。
- 求将 \([1,n]\) 全部治愈的最小代价。
- \(n\leq 10^9,m\leq 10^5,t,c\leq 10^9\)。
维护方法是之前场切的一道 CF 题,但是显然我差在第一步转化。
时间上没有可做性,于是只按 \(1\to n\) 的顺序考虑覆盖,设 \(f(i)\) 表示覆盖 \([1,r_i]\) 的最小代价,那么:
然后就是一个类似 Dijkstra 的转移,初始节点是 \(l_i=1\) 的计划们。
发现指向一个点的边权都一样,相当于一个点只会被扩展一次。
那就和那道 CF 题一模一样,拿一棵线段树,拆绝对值,支持单点删除和区间查询即可。

浙公网安备 33010602011771号