loading

康复训练

CF1845E Boxes and Balls

给定长为 \(n\) 的 01 序列和一个整数 \(k\)。每次操作可以选择相邻两个数,满足两个数不相同,然后交换这两个数。求最终能得到多少种不同的序列。

\(n,k\le 1500\)

分析

首先注意到如果我们枚举最终的 01 序列,那么所有的合法的操作方案消耗的步数都是相同的,均为两个序列中第 \(i\) 个 1 出现的位置差的和。暴力的 DP 记录前 \(i\) 个位置选了 \(j\) 个 1 操作步数 \(k\),直接做就是三次方的。

由于状态已经三次方,而且状态看起来不能直接压掉一维信息,考虑发掘一些性质。发现操作次数的最大值能到达 \(O(n^2)\) 级别,然而 \(k\) 只有 \(O(n)\),这启发我们在“压掉操作”的方向思考问题。考虑如果当前有连续的 \(len\) 个 1 想要向后填,那么此时的步数已经为 \(O(len^2)\),由于 \(k\) 只有 \(O(n)\),所以 \(len\) 只有 \(O(\sqrt k)\)。改一下状态,\(j\) 改为此时有多少个 1 想要往后填。在这个定义下 \(j\) 可以为负,此时代表有 \(j\) 个 0 要往后接纳要往前填的 1。

时间复杂度 \(O(nk\sqrt k)\)

代码丢了。

P8360 [SNOI2022] 军队

\(n\) 个点,每个点有权值 \(a_i\) 和颜色 \(c_i(1\le c_i\le C)\),有 \(q\) 次操作:将 \([l,r]\) 内颜色为 \(x\) 的所有点的颜色改成 \(y\);将 \([l,r]\) 内颜色为 \(x\) 的所有点的点权加 \(y\);查询 \([l,r]\) 点权和。

\(n,q,C\le 2.5\times10^5,6\text{s},1\text{GB}\)

分析

这种问题一看就不大能 polylog,考虑分块,散块操作显然,整块一操作可以通过对颜色建点(注意一个颜色可能被先后多次建点),然后用并查集实现。操作二可以在并查集的基础上在每个点维护一个 tag 和 siz 实现。操作三直接在进行操作二时动态处理块内和即可。考虑散块重构,一个点最终的加和是它的所有祖先的 tag 之和。为了处理出这个东西,一种好写的做法是发现父亲编号大于儿子,然后倒着处理,这样就不用递归了。最终的颜色可以通过记录每个点代表的颜色 col 来实现。复杂度单根号。

但此时空间复杂度也是单根号的,实现不精细很可能被创飞,考虑到原题允许离线,所以我们离线下来后对每个块单独做就行了,这样只需要存这个块的信息,空间复杂度降为线性。

P3268 [JLOI2016] 圆的异或并

\(n\) 个圆,保证要么包含要么不交。求被奇数个圆覆盖的面积除以圆周率的结果。\(n\le 2\times10^5\)

分析

考虑对圆建一棵树,那么在奇数深度上的面积为正贡献,偶数深度上的面积为负贡献。考虑求圆的深度,扫描线后将整圆分成上半圆和下半圆,考虑在这条线上该圆上方的第一个半圆,如果这是一个下半圆,那么该圆和下半圆所属圆有相同的父亲;如果是上半圆,那么上半圆所属圆是该圆的父亲。考虑用 set 维护前驱后继,半圆的权值即为半圆与扫描线的交点 y 坐标。由于圆两两在圆上无交,所以无论扫描线扫到那权值的偏序关系不会改变。但是需要注意的是上下半圆的交点是重合的,可能会引起不必要的麻烦,所以选择将加入时间延后,删除时间提前。复杂度单 log。

P7515 [省选联考 2021 A 卷] 矩阵游戏

有一个 \(n\times m\) 的矩阵 \(a\),另有一个 \((n-1)\times(m-1)\) 的矩阵 \(b\),满足 \(b_{i,j}=a_{i,j}+a_{i+1,j}+a_{i,j+1}+a_{i+1,j+1}\)

给定最终的 \(b\),要求构造一个合法的 \(a\) 满足 \(0\le a_{i,j}\le 10^6\),需要判断解的存在性。

\(n,m\le 300\)

分析

不妨让第 \(n\) 行和第 \(m\) 列都为 0,那么此时的 \(a_{i,j}\) 可以唯一确定。然后发现对一行/一列交替加某个定值,\(b\) 不会改变。不妨设第 \(i\) 行交替加 \(r_i\),第 \(j\) 列交替加 \(c_i\)。那么矩阵会变成这个样子:

+r1+c1 -r1+c2 +r1+c3 -r1+c4 ...
+r2-c1 -r2-c2 +r2-c3 -r2-c4 ...
+r3+c1 -r3+c2 +r3+c3 -r3+c4 ...
+r4-c1 -r4-c2 +r4-c3 -r4-c4 ...
...

写成约束的形式就是 \(0\le r_i+c_j\le 10^6\)\(0\le r_i-c_j\le 10^6\) 等形式。后者可以写成差分约束的形式,但前者不能。考虑变换一下 \(r_i,c_j\),令第奇数行的 \(r_i\) 和第偶数列的 \(c_j\) 为它们的相反数,那么对于 \(r,c\) 同号的点有一个取了反,异号的点有两个或零个取了反,所有的限制都是差分形式,跑差分约束即可,最后别忘了把取反后的那些 \(r_i,c_j\) 取反回来。

\(n+m\) 个变量,\(2nm\) 个限制,所以复杂度三次方。

P10785 NOI2024 集合

给定两个长度为 \(n\) 的集合序列 \(a,b\),其中集合都是大小为 3、值域为 \([1,m]\) 的不可重集。定义两个集合序列等价当且仅当存在一个 \(m\) 阶排列 \(p\) 使得将第一个序列的所有集合的元素 \(x\) 都变成 \(p_x\) 后与第二个序列完全相等。\(q\) 次查询 \(a,b\) 的子区间 \([l,r]\) 是否等价。

\(n\le 2\times10^5,m\le 6\times10^5,q\le 10^6\)

分析

都排列置换相等了,自然考虑两个序列的所有数值的某一信息组成的可重集是否相等,由此我们得出一个结论:两个序列等价当且仅当 所有数出现的下标构成的集合 构成的集合相等。充分性和必要性都不难证。而这个东西考虑设计一个哈希函数来判断等价,内部的哈希函数随便乱造一个好维护的就行,外部的哈希函数最好别选位运算,我选的是内部异或(给每个下标赋一个随机权值然后异或起来,当然也可以构造多项式函数等)外部加法,模数自然溢出。

考虑查询。不难发现一个区间合法它的子区间合法,所以这东西有单调性,可以双指针,对于每个左端点只需要维护最大的合法右端点即可,复杂度线性。

P10786 NOI2024 百万富翁

交互题,给定长度为 \(n\) 的权值互不相同的序列,你需要找到其中的最大值的下标。你可以发送若干次请求,每次请求包括若干次询问 \((x,y)\),交互库会返回权值较大的那一个的下标。

\(n=10^6\),设 \(t\) 表示请求次数,\(s\) 表示询问总次数,满分要求 \(t\le 8,s\le 1099944\),有份要求 \(t\le 20,s\le 2\times10^6\)

分析

考虑到我们只能通过询问完全图知道一个集合的最大值,而 \(t\) 又如此小,我们必须精细的规划每一层每一块的大小。根据不等式知识,总长、块数一定时,要想询问次数最小,最优解是让块长尽可能平均。所以我们设 \(f_{i,j}\) 表示用了 \(i\) 轮剩余 \(j\) 个数字的最小次数,转移枚举块数转移,复杂度 \(O(tn^2)\)。然而要跑出答案肯定一时半会跑不完,打几个范围千和万左右的数据可以发现,最优解的前四项块长都是 2,所以我们考虑钦定前四项块长为 2,再做上面的 DP,复杂度能除掉一个 \(512\),跑个几秒就能跑出最优解了。

一种合法的最优解:

1099944
500000 250000 125000 62500 20832 3472 183 1

QOJ11548/Gym105666D

给定 \(n\times n\) 坐标系上的 \(n\) 个点,每个点有类型 LR/UD,保证每行每列至多一个点。现在要给所有 UD 点从该点出发引一条向上或下指的射线,LR 点从该点出发引一条向左或右指的射线,求所有射线不相交的方案数,模数 \(10^9+7\)

题解:发现如果所有 LR 确定了,UD 的贡献也确定了,反之同理。按列处理,分为两种情况讨论:

  1. LLLLRRRR 型,即存在一个分界点 \(i\),使得前 \(i\) 列的 LR 点左指,后面的列的 LR 点右指。枚举分界点,每个 UD 点的贡献可以 \(O(n)\) 计算。
  2. LLLLRLRRR 型,即存在一个点 \(i\),使得 \(i\) 列上的点往左指,\(i\) 前面的第一个 LR 点向右指。为了不算重,枚举并钦定 \(i\) 是第一个满足这个条件的点。此时所有 UD 点的方向可以确定,根据 UD 点的方向可以推出 LR 的贡献,注意为了满足钦定条件 \(i\) 前面的点的方案数要特殊照顾一下(不是直接的 \(2^{cnt}\))。

总复杂度 \(O(n^2)\)

CF2096F Wonderful Impostors

如果一个区间是 0 区间,那么就相当于区间内钦定填 0,而如果一个区间是 1 区间,那么如果该区间被 0 区间的并所包含,那么就不合法了。考虑维护线段树,0 区间的话就区间加 1,1 区间的话就查询区间最小值是否为 0。

首先不难发现固定 \(l\),合法性关于 \(r\) 具有单调性,所以可以考虑双指针。考虑加入区间,如果加入 1 区间,那么查一下区间最小值就行;如果加入了 0 区间,现在区间内全都不为 0 了,考虑找到两边第一个为 0 的地方,获得一个极长没有 0 的区间,然后查一下有没有 1 区间被其完全包含即可,这个还是可以线段树+底层 set/可删堆 维护每个右端点的最大左端点,然后查一下区间最大值是否小于极长区间的左端点即可。删除直接删就行,对当前局面合法性没有任何影响(原区间都合法删掉开头必然合法),复杂度单 log。

CF2127F Hamed and AghaBalaSar

阅读伪代码可以发现一个序列的权值等于序列所有最大值的和 - 所有最大值后一位的值的和 - 第一位的值。考虑拆贡献,先求第一部分,枚举最大值,分成 不在最后一位的最大值 和 在最后一位的最大值 两种情况讨论,如果设 \(f(n,m,k)\) 表示长度为 \(n\) 的序列,\(\sum a_i=m,0\le a_i\le k\) 的方案数,则两种情况方案数分别为 \((n-1)f(n-2,m-2k,k),f(n-1,m-2k,k)\)。然后考虑第三部分,发现如果接着枚举这一位的数复杂度就炸了,注意到如果设 \(g(n,m,k,p)\) 表示在 \(f(n,m,k)\) 的条件下 \(a_p\) 的和,则对于所有 \(p\)\(g(n,m,k,p)\) 都相等,因为你交换两个位置仍然满足条件,那么对于第一位的值之和,可以用所有位的值之和除掉序列长度得到,答案即为 \(\frac{(m-k)f(n-1,m-k,k)}{n-1}\),第二部分的贡献也是同理的,由于相当于是对所有位都求和一遍,所以不需要除以序列长度了,答案是 \((m-2k)f(n-2,m-2k,k)\),由于第 \(n-1\) 个位置的下一个是 \(n\),所以这部分贡献还要在算一次。

现在要对每个 \(k\)\(O(1)\)\(f(n,m,k)\),求单个 \(f\) 可以考虑容斥,钦定若干个位置 \(\ge k+1\),然后剩余部分的贡献就是插板法,由于钦定的数量大于 \(\frac{m}{k}\) 就没有贡献了,所以复杂度 \(O(\frac{m}{k})\),故总复杂度是调和级数。

HTCSP-S2025 C 阳光收集

这下真菜完了。

考虑会算重当且仅当删除一个字符后剩下的相等,于是我们钦定每次只能选连通块的开头删掉。你要是往记录连通块数量方向上想连个多项式复杂度做法都没有,我们可以考虑记录每个元素被删除的时间,那么需要满足其之前第一个删除时间大于它的颜色和其不同(这显然是充要的)。维护这个东西可以区间 dp 记录 \(f_{l,r}\) 表示填 \([l,r]\) 的方案数,且 \([l,r]\) 内的删除时间小于 \(l-1\)。转移考虑枚举最大值的位置,合并是一个组合数的贡献。复杂度 \(O(n^3)\)

P4383 [八省联考 2018] 林克卡特树

发现是恰好选 \(k\) 个的类型,打个表发现有凸性(也可以费用流证),套个 wqs 二分后相当于截掉若干边使得截边的代价为惩罚值,然后在每个连通块内选出一条直径。直接设 \(f_{i,0/1/2}\) 表示以 \(i\) 为顶点的子树内,\(i\) 所属的连通块尚未选边/正在选边/选边完成的最大价值。转移并不困难,时间复杂度 \(O(n\log V)\)

posted @ 2025-07-05 19:51  dcytrl  阅读(39)  评论(5)    收藏  举报