近期总结 2024.2.28
Ynoi 简单题专场。
Luogu6783 [Ynoi2008] rrusq
题意:平面上有 \(n\) 个点,第 \(i\) 个为 \((i,p_i)\),其中 \(p\) 为给出的 \(1...n\) 的排列。给出 \(m\) 个矩形和 \(q\) 个询问,每次询问给出 \(l,r\),求编号 \([l,r]\) 矩形并覆盖了多少个点。
\(1\le n,m\le 10^5,\space 1\le q\le 10^6\)
容易想到离线,然后 \(i=1...m\) 依次扫描每个矩形。对于每个矩形,我们考虑更新他覆盖的所有点。
我们考虑维护 \(s_i\) 表示有多少个点被矩形 \(i\) 覆盖,且 \(i\) 在扫描过程中是最大可能的矩形编号。
那么每次更新覆盖的点时,把原来已经被覆盖过的点修改,在 \(s\) 上单点修改,还要支持区间 \([l,r]\) 的查询。
考虑矩形问题,可以用 KDT。当找到一个覆盖的区域打标记时,暴力递归子树内有标记的点,把标记清空,均摊 \(O(\sqrt n)\)。
在 \(s\) 上单点修改,可以使用 \(O(1)\) 修改,\(O(\sqrt n)\) 查询的分块,时间复杂度 \(O((m+q)\sqrt n)\)。 记录
Luogu5069 [Ynoi2015] 纵使日薄西山
题意:给出 \(n,a_{1...n}\),每次操作选择 \(a\) 中的最大值 \(a_x\)(如果有多个则选择位置最小的),然后令 \(a_{x-1},a_x,a_{x+1}\) 都减去一。多次询问,每次单点修改,求出最少需要多少次操作满足 \(\forall i\in [1,n],a_i\le 0\)。
\(1\le n\le 10^5,\space 1\le a_i\le 10^9\)
观察性质,首先对于一个数 \(a_i\),如果比 \(a_{i-1},a_{i+1}\) 都要大,那么我们一定会操作 \(a_i\)。
考虑操作 \(a_i\) 多少次,容易发现如果某一次选择了 \(a_i\) 操作,那么整个操作过程中一定不会操作 \(a_{i-1},a_{i+1}\),可以感性证明。
因此,我们可以给操作过的 \(a_i\) 填上 \(1\),给没有操作过的 \(a_i\) 填上 \(0\),我们得到了一个 \(01\) 序列。
观察这个 \(01\) 序列,合法的条件是:
-
任意两个 \(1\) 不相邻。
-
连续若干个 \(0\) 的长度不超过 \(2\)。
-
对于每个 \(0\),存在一个相邻的 \(1\) 满足在 \(a\) 中 \(1\) 对应的值比 \(0\) 对应的值大。
我们还可以猜一个结论:一个确定的 \(a\) 序列对应唯一一个合法的 \(01\) 序列!而且,通过手玩我们无法推翻这个结论。
所以我们不难产生一种新的思路:尝试填写这个 \(01\) 序列,并保证合法,最后 \(01\) 序列中所以 \(1\) 在 \(a\) 中对应的值的总和就是答案。我们不需要在意这个总和是大是小,因为只有唯一的一种填写方案。
考虑 dp,设 \(f[i,0/1/2]\) 表示填写了 \(01\) 序列中前 \(i\) 个位置的对应数值总和最大值,并分三种情况:
-
第 \(i\) 个位置为 \(1\)。
-
第 \(i\) 个位置为 \(0\),第 \(i-1\) 个位置是 \(1\),并且 \(a_{i-1}>a_i\)。
-
第 \(i\) 个位置为 \(0\),但是第 \(i-1\) 个位置不满足第二种情况的条件。
第三种情况需要下一个位置填 \(1\),并且数值大于 \(a_i\)。
其实就是个简单的动态 dp,容易用线段树 + 矩阵乘法优化。
时间复杂度 \(O(n\log n)\)。 记录
Luogu6109 [Ynoi2009] rprmq1
题意:一个 \(n\times n\) 的矩阵,初始时所有格字权值为 \(0\)。有 \(m\) 次修改和 \(q\) 次查询,所有查询在修改之和。每次修改给出一个矩形和权值,表示把矩阵上的矩形所有格字权值加上对应权值;每次查询给出一个矩形,求矩形覆盖区域的权值最大值。
\(1\le n,m\le 5\times 10^4,\space 1\le q\le 5\times 10^5\)
考虑按行来猫树分治。
显然左右两边的最大值是独立的,可以分开求。考虑左边,一个跨过 \(mid\) 的矩形,我们需要处理的是左边部分的一段后缀,从 \(mid\to l\) 扫描。
我们需要支持加入一些修改的矩形,会发现一个修改矩形被用到,但不一定要跨过 \(mid\)。参考线段树的思想,我们把矩形的行区间放到若干个分治节点上。
然后,我们把每个矩形差分掉,扫描线。每次需要在矩形的列区间上做区间加,对于一个查询,我们需要支持查询一个一段后缀中一个区间的最大值,发现其实就是区间历史最大值。
还有一些细节,注意 \(-1\) 标记一定要在 \(+1\) 标记前处理才不会影响历史最大值。一个矩形覆盖一个分治区间时,可以先区间加,视为初始状态,然后整个区间递归结束后再减去。
为了清空,还需要支持线段树全局节点令 \(hmx\) 赋值为 \(mx\),可以打一个 \(cln\) 标记表示这个操作。注意当下传 \(cln\) 标记时,需要先把儿子的区间加标记传到孙子,以免两者互相影响。
时间 \(O(m\log ^2n+q\log n)\)。记录
Luogu5064 [Ynoi2014] 等这场战争结束之后
题意:一张 \(n\) 个点的图,点有权值,初始没有边,\(m\) 次操作,支持:
-
连一条无向边
-
回到历史某个时刻的状态
-
查询一个点所在连通块中第 \(k\) 小的点权
\(1\le n,m\le 10^5\),卡时间、空间。
考虑值域分块,每个询问我们都要先确定答案在哪个块,然后在块内暴力查。
建立操作树,用可撤销并查集维护连通性。
维护 \(s_{i,j}\) 表示以 \(i\) 为根的连通块中值域在第 \(j\) 个块的数字个数,暴力查询,\(O(n\sqrt n \log n)\)。
一种空间的优化是每个块的判断分别 dfs,空间 \(O(n)\),时间 \(O(n\sqrt n\log n)\)。
但是可以不完全每个块分别,考虑 块大小 \(B_1\),\(B_2\) 个块一次 dfs,空间 \(O(nB_2)\),时间 \(O(mB_1\log n+m\frac{n}{B_1B_2}\log n)\)。
取 \(B_1=\sqrt{\frac n{\log n}},\space B_2=\log n\),时间 \(O(m\sqrt{n\log n})\),空间 \(O(n\log n)\)。 记录