2025 山东三轮省集
Day 0
Day 1
\(100 + 35 + 20\),\(\text{rk} 36\)。
后面都以线下榜为准(因为我线下分更高)。
T1
相当于是求子树内最后一次操作的颜色,然后如果最后几次操作的颜色相同,取第一次操作的时间。
可以用线段树维护出区间内执行操作的最大时间和次大时间(要求和最大颜色不同),那么答案一定就是次大时间的后继,在扫描线一遍求后继即可。
T2
如果只求出现次数为 \(m\) 个数的个数可以分块做到 \(O(n\sqrt n)\),对于本题,直接暴力做到 \(O(\dfrac{n^2}{\sqrt m})\),可以平衡到 \(O(n^{\frac 7 4})\),可以直接通过。
这离正解只有一步之遥。
我们只需要记一个块的最大最小值,查询的时候直接找这之间的 \(m\) 的倍数即可,这样做时间复杂度是 \(O(n \sqrt n)\) 的!
由于只有散块加才会改变一个块的极差(并且只会让一个块的极差增加 \(1\)),因此所有块的极差之和是 \(O(n)\) 的,因此复杂度就是 \(O(\dfrac{n^2}{m})\),由于 \(m \ge \sqrt n\),时间复杂度为 \(O(n\sqrt n)\)。
T3
太难了,不会。
这据说是新的大分块?
HDU6843
和今天 T3 差不多。
CF1814F
首先线段树分治。到叶子的时候就是这个时刻图的形态。给 \(1\) 所在的并查集打一个标记, 然后并查集分裂合并的时候标记都可以直接下传。
QOJ8704
将队伍看成一棵树(一个节点的儿子有顺序),修改就相当于加叶子,或者是将一个节点扔到另一个节点的下面。
这个过程 LCT 就直接做完了,但是还有更好的做法。
可以将树表示成括号序列,直接用平衡树维护这个东西。
比如说 \((1,2),(2,3),(2,4)\) 这棵树就可以表示成 \([1,2,3,-3,4,-4,-2,-1]\)。
这样查询 \(i\) 的子树大小就可以直接求出 \(i\) 和 \(-i\) 的距离就行。
插入也是简单的。
P12462
斯坦纳树有点吓人,仔细一看就是虚树。
考虑 \(q = 1\) 怎么做,这就是一个我不会的经典问题,建出虚树,以直径端点为根长剖,取前 \(k\) 长的链即可。
考虑 \(K = 2\) 怎么做,发现就是求直径,可以线段树直接维护。
将两个结合起来,在每个线段树上维护最优的 \(K\) 个点,猜个结论,这个东西和直径一样。\(pushup\) 直接将左右儿子的 \(k\) 个点归并建虚树,跑 \(q = 1\) 的做法即可。
发现 \(q \le 10^4\),可以把序列先分成 \(O(q)\) 段再建线段树。
时间复杂度 \(O(n\log n + qk \log q)\)。
仅限口胡,可能实现有些细节。
未公开题目
点击此处输入题面
我一定在某个地方见过这个东西,但是没听过正解。
可以对每种颜色建虚树然后二维数点算出哪些边被断掉了。这样看起来是对的但是虚树中有一些虚点导致如果断出只有虚点的联通块,这个东西是没有贡献的。
这个东西虽然是错的,但是我们可以先把这个东西算出来,再减去只含虚点的联通块数量即可。
Day 2

感谢 lxl 的优秀题目名,让我重新回味美国山海经。
\(100 + 30 + 8\),\(\text{rk} 14\)。
T1
操作区间都是 BFS 序的连续段,进一步地,包含别的区间的区间是没有用的,此时区间是顺序排列,不互相包含的。所以一个位置只会对区间的一个连续段造成影响。至此直接双指针即可。
T2
如果你会半平面数点,那么就可以直接获得 \(30\) 分。(我写的基于随机数据,对平面分块)。
正解是旋转扫描线,不基于随机,我会学的。
lxl 给了一个 \(n\sqrt m\) 的 \(\text{KD-Tree}\) 做法(基于随机),但是卡常卡不过去。
先对平面做一些反演操作:推推式子将半平面变成点,将点变成半平面。每一次拿出相同颜色的半平面(原来的点)一块操作,在 \(\text{KD-Tree}\) 上面打 \(\text{tag}\)。考虑到我们真正需要的是每个点(原来的半平面)被覆盖次数的平方。所以一种颜色打完 \(\text{tag}\) 之后我们将修改的点在 \(\text{KD-Tree}\) 上形成的虚树(就是所有修改访问过的点集的并)拿出来并将标记全部下放,现在每个位置被覆盖多少次就已经都被 \(\text{push}\) 到一个点上了。直接给虚树的叶子节点的标记加上新标记的平方即可。复杂度显然是 \(n\sqrt m\) (直接修改是对的,然后虚树复杂度和将修改再执行一遍无异)。
注意最开始反演的时候可能有一些正负号的问题,直接对 \(A = 0,A < 0,A > 0\) 分别跑一遍即可。常数非常大,一位卡常大师已经在省集 OJ 上通过了(在洛谷没过),但是我还没过。
\(2025.6.4\) 终于过了,lxl 教会我厉害卡常小技巧。
把 \(\text{kd-tree}\) 的前几层删了,此时原序列变成若干块,对每一块分别做修改,也就是逐块处理,这样由于每次修改的点数很少,能卡进一些神秘的缓存然后就跑得飞快,最慢点不到 5s,立马变成洛谷最优解。
T3
数据结构也能非传统?这也太神秘了。

首先你要手写编译器,否则会比较麻烦,下发文件已经给了。
搞 \(n\) 个块,相邻两个块之间放 \(-2\infty\),每个块前面放 \(+\infty\)。这样询问全局最大子段和就是每个块前缀 \(\max\) 的最大值。一行一行解决,考虑 \(c_{i,j} = \max_{k=1}^{n} a_{i,k} + b_{k,j}\),第 \(k\) 块开头放上 \(a_{i,k}\)。
然后构造序列使得全局加上 \(jV\) 后,每块最大前缀和刚好是 \(b_{k,j}\),令其为 \(b_{k,j} - b_{k,j-1} - jV + C\) 即可(\(C\) 为常数使得 $ C < V \land C > b_{k,j} - b_{k,j-1}$)。每次加上 \(V\) 并询问全局最大子段和,第 \(j\) 次即为 \(c_{i,j}\) ,换到下一行仅需 \(O(n)\) 次单点修改。
抄的 std。
Day 3
\(100 + 60 + 20\),\(\text{rk} 6\)。
打的最好的一集。
T1
原题是 QOJ9698。
既有取 \(\min\) 又有取 \(\max\) 实在是太麻烦了,我们先把所有取 \(\min\) 操作拿出来,设其中最小的那一个为 \(x\)。那么首先原序列应对 \(x\) 取 \(\min\),\(\le x\) 的取 \(\max\) 操作没有用(一定会被原样执行)。这样就变成了所有操作的参数全部 \(> x\),然而原序列全部 \(< x\),所以原序列没有用。
进一步地,我们将取 \(\min\) 操作从小到大排序。取 \(\max\) 操作都可以放在任意对 \(c\) 取 \(\min\) 操作的前面,可以看作对 \(c\) 取 \(\max\)。这就相当于我们扔掉所有取 \(\min\) 操作,然后取 \(\max\) 可以对原来的这个值,或者任意比它小的取 \(\min\) 操作的值取 \(\max\)。
于是记 \(f(l,r,k)\) 表示通过取 \(\max\) 操作将 \([l,r]\) 这个区间全部变成 \(\ge k\) 的方案数(序列种类数)。转移其实是不难的。时间复杂度 \(O(n^4)\) 或 \(O(n^5)\)。\(O(n^4)\) 需要一些预处理辅助转移,我场上写的 \(O(n^5)\) 并过了,赛后尝试在 qoj 上 hack 自己,结果 hack 不掉,跑了 2.7s(时限 3s,\(O(n^4)\) 在这种数据中会跑 400ms 左右)。
T2
洛谷 P10009。
前面几档暴力加上 \(\text{bitset}\)。
全局修改的部分,不妨将差分看成在网格图上走,一开始 \(i\) 位置上有一个值,\(t\) 次修改之后到达 \(j\) 的方案数为 \(\dbinom{t}{j-i}\),因为我们只关心其奇偶性,所以可以运用 \(\text{Kummer}\) 定理,这个东西就是 \([j-i \subseteq t]\)。只有全局修改时,我们只要查询有多少 \(j\) 使得 \([j-i \subseteq t]\),根号分治就可以做到 \(O(n \sqrt n)\)。
考虑区间修改的时候怎么办,这个东西看起来很不好做,考虑分块,\(B\) 个一块(其中 \(B\) 是 \(2\) 的整次幂)。那么一次修改分为整块打 \(\text{tag}\) 和散块重构,打 \(\text{tag}\) 的意思就是这个块在新的一个时刻中,左端点异或上了某个值。可以看出由于块内计算贡献距离不会超过 \(B\),因此 \(\text{tag}\) 的时间大小是可以对 \(B\) 取模的。
散块重构的时候,先通过高位前缀和计算出 \(\text{tag}\) 对每个位置的贡献,和块内这段时间的贡献。这两个东西都是简单的,时间复杂度 \(O(B \log B)\)。
现在还有什么问题呢?我们发现打 \(\text{tag}\) 的时候需要获取某个块最后一个位置的值,对于这个位置,块内贡献可以散块重构的时候高位前缀和算出,时间复杂度同上,此外因为 \(B\) 是二的整次幂,所以一个 \(\text{tag}\) 对块的右端点 \(r\) 产生贡献当且仅当 \(r - l \subseteq t\),而 \(r - l\) 二进制下是全 \(1\),所以 \(t\) 必须是 \(B - 1\),只需查询一个单点即可。时间复杂度 \(O(1)\)。
这样时间复杂度是 \(q\dfrac{n}{B} + qB \log B\),可以平衡到 \(q \sqrt{n \log n}\)。
T3
好难。据说是设计出暴力 DP 之后发现 DP 数组斜率只有 0,1,2,进而轻松维护转折点。
Day 4
\(100 + 0 + 34\),\(\text{rk} 8\)。
T1
神秘大分讨。
将列表按照值域排序,考虑到最后肯定是要保留列表中的一个在原序列的位置单调递增的子段。所以我们枚举每个极长的子段并且看能不能保住这个子段。
设这个子段范围是 \([l,r]\),长为 \(len\),第一列表中子段左边有 \(a\) 个数,右边有 \(b\) 个数,第二列表中在 \((a_{l-1},a_{r+1})\) 中有 \(c\) 个数,更小的有 \(d\) 个数,更大的有 \(e\) 个。
现在操作是我可以每次将 \(c,d,e\) 中的一个减 \(1\),并分别将 \(a,len,b\) 加 \(1\),并且奇数轮时会让 \(b\) 减 \(1\),偶数轮让 \(a\) 减 \(1\),若 \(a,b = 0\) 则让 \(len\) 减 \(1\)。通过复杂的分类讨论我们可以轻松获得最优方案:
-
首先我们一直消耗 \(c\),如果此时 \(a,b\) 都变成 \(0\) 就直接结束了。
-
否则在任意时刻若 \(a = 0\) 则 \(d\) 和 \(c\) 起同样作用,一直消耗 \(d\) 和 \(c\) 即可,最后如果 \(b = 0\) 则结束,\(c = d = 0,b \neq 0\) 就没救了。 \(b = 0\) 时同理。
-
如果 \(a \neq 0 \land b \neq 0\),那么我们选一边一直塞东西直到另一边变成 \(0\)。需要一些计算。选哪一边都有可能,都算一遍就可以。
T2
神秘计算几何,太恐怖了。
有 \(51pts\) 的弱智部分分,但是我不会写代码,只写了 \(0pts\)。
下面直接复制比赛题解:
关键结论:答案等于 \(\min(\lfloor n/3\rfloor,n-c)\),其中 \(c\) 表示平面上的一条直线 \(l\) 最多同时穿过多少个点。
如果 \(3c \le 2n - 4\),我们随便剥掉一个靠边的三角形 \(\triangle{ijk}\),答案不会改变。
- \(i\) 选择 \(y\) 坐标最大的点 \(i\)。如果有多个选择 \(x\) 最小的。
- \(j\) 选择 \(i\) 向正左的射线逆时针旋转遇到的第一个点。如果有多个选择 \(Dis(i,j)\) 最小的。
- \(k\) 选择 \(i\) 向 \(j\) 引出的射线顺时针旋转遇到的第一个点。如果有多个选择 \(Dis(j,k)\) 最小的。
我们不需要担心 \(\triangle{ijk}\) 与剩下的三角形相交。更一般的,对于任意一条直线 \(l\),可以用 \(l\) 把整个平面切分成两个半平面分别求解(其中 \(l\) 穿过的点必须切分成一个前缀加一个后缀)。只要两边分别形成合法的解,拼起来一定是合法的解。
如果 \(3c \ge 2n - 3\),我们任意找出一条直线 \(l\) 穿过 \(c\) 个点,不妨设 \(l\) 不平行于 \(y\) 轴。
我们把 \(l\) 上的点从左到右排序,同时根据 \(l\) 这条直线把平面划分为上下两个部分。每次剥掉一个靠边的三角形:
- 拿出最靠右第二个第一个点 \(i,j\),\(k\) 选择 \(i\) 向 \(j\) 引出的射线逆时针旋转遇到的第一个点。如果有多个选择 \(Dis(i,k)\) 最小的。
- 拿出最靠左第二个第一个点 \(i,j\),\(k\) 选择 \(i\) 向 \(j\) 引出的射线逆时针旋转遇到的第一个点。如果有多个选择 \(Dis(i,k)\) 最小的。
以上做法只有在 \((n,c) = (6,3)\) 的情况下会出错。这个情况直接暴力枚举 \(\dbinom{6}{3}\),一一检查是否合法即可。
有一种聪明的办法可以绕开计算 :一直按照 \(3c \le 2n - 4\)
的做法做直到剩下所有的点共线,然后把最后形成的三角形一个一个回退掉,直到计算出来损失掉的点数 \(\le 2\) 或者已经全部回退干净为止。最后那条直线直接取成 \(l\) 即可。
以上所有东西通过叉积实现,不需要算夹角。使用全整数实现可以避免浮点数精度问题。
时间复杂度 \(O(n^2)\)。
T3
神秘科技题,有原题 luogu P9109。
直接暴力获得 \(1\) 分的好成绩(
将问题看作矩阵上走求最长路,容易猫树分治做到 \(O(n^3 + qn)\),可以获得 \(34\) 分。
使用神秘科技 bitset 求最长公共子序列,做到 \(O(\dfrac{n^2q}{w})\) 或者 \(O(\dfrac{n^3}{w} + nq)\) 可以获得随机分数,最多得 \(67\) 分。
还是去看原题题解吧,真的写不动了。
Day 5
\(100 + 100 + 0\),\(\text{rk} 4\)。
T1
一个一个把人加进去,设 \(t_i\) 表示当前 \(i\) 点最后有人的时间为 \(t_i\)。然后手模一下,插入一个点 \(x\) 相当于给 \(x\) 点到根路径中的所有点 \(i\) 自上向下做如下操作:
- \(t_i = t_{fa_{i}} = \min(t_i,t_{fa_{i}})\)
然后对于所有点 \(i\):
- \(t_i = t_i + 1\)
然后 \(t_x = t_x + a_x\)。
这个东西如果你先重链剖分,并且只看重链上的前缀最大值(其他值对统计答案没有用处),就可以看作前缀最大值全部向上移动一格,再全部 \(+1\),然后单点修改一次。直接用平衡树暴力维护,类似 P9999。时间复杂度 \(O(n \log ^2 n)\)。
T2
真就唐氏题,咋放 T2 了。
考虑每一对数的贡献。写出来。然后再展开展开,就可以得到最终结果:
设 \(s_1\) 是区间和,\(s_2\) 是区间 \(i \times a_i\) 的和。则答案就是:
这个东西还可以因式分解,但是没什么用。
线段树直接维护会被卡常,换成树状数组或者直接加上 fread,fwrite 就行。
T3
场上没看。
把加入变删除,每次需要保证删除的点不是割点并且和外界(无穷远处联通)。
对于不要求字典序的部分只需要从左上开始删即可。对于要求字典序的部分,直接暴力可以做到 \(O(n^2)\),考虑能不能更高效的维护可以被删的点。
网格图判断一个点是不是割点有更高效的方式:对于一个点 \((x,y)\),如果 \((x+1,y+1)\) 没有被删,且 \((x+1,y)\),\((x,y+1)\) 为空格,且通过空格联通,且 \((x,y)\) 还有其他和他八联通的点,那么他就是割点,其他三个方向同理;如果 \((x+1,y)\) 和 \((x-1,y)\) 没被删且 \((x,y+1)\) 和 \((x,y-1)\) 是空格且连通,那么他也是割点,其他一个方向同理。这样对于一个点能够改变他是否是割点的空格连通块合并次数是 \(O(1)\) 的。只需精细实现就可以 \(O(n \log n)\) 维护可以被删除的点集。
太精细了,所以我不想写。
Day 6
\(50 + 70 + 0\),\(\text{rk} 22\)。打得真烂!
T1
钦定有若干个回文串,那么对这个串就有诸如某两个字符相等的限制,相等的字符之间连边,那么有 \(k\) 个连通块时答案就是 \(\sigma ^ k\)。考虑暴搜,直接暴力维护前 \(k\) 个字符的连通性,再看是否钦定这个位置为一个回文串的结尾并更新答案,这是简单的,设有 \(m\) 个状态时间复杂度就是 \(O(nmk)\),经过暴搜 \(m\) 是 \(9 \times 10 ^ 4\) 左右。只能获得 \(50\) 分。
然后我他妈的就不会了。实际上你只要把自动机提前建出来然后在上面跑就可以了。时间复杂度 \(O(mk + nm)\)。
T2
注意到每一位是互不影响的。如果对于第 \(k\) 位,序列中存在一个数使得这一位是 \(1\) 的话,那么对答案就有 \(2^{n-1} \times 2^k\) 的贡献。
对于一个答案 \(x\) 我们将 \(x\) 二进制拆位,为 \(0\) 的位在序列中必须全是 \(0\),为 \(1\) 的位在序列中至少有一个是 \(1\),也就是 \(2^n - 1\) 种方案。所以原序列有 \((2^n - 1)^{popcount(x)}\) 种方案。
所以我们是要求出最小的 \(k\) 使得 $(2^n -1) ^ k \equiv x \pmod m $,答案就是 \(2^k - 1\)。
这就是 BSGS,套用 exBSGS 即可,但是我不会这个,没时间推了,只拿了不需 exBSGS 的 \(70 pts\)。
T3
树上分糖果,树剖然后套用分糖果即可,时间复杂度 \(O(n \log ^ 2n)\)。出这么裸的原题也太神秘了吧!虽然我没有做过。
Day 7
\(100 + 45 + 25\),\(\text{rk} 14\)。
T1
推起来还挺顺。
发现倒水的过程看似非常具有后效性,实则不然。
从第一瓶水开始,一定是不断往后倒水,直到第一次往前倒水,后面就不会再进行操作了。
发现只有往前倒水会具有后效性,仔细一想这个东西也没有后效性,因为后面的水一定是从前面的水一次一次减过来的,所以如果往回倒 \(x\) 单位的水,那么前面的水瓶 \(i\) 可以接下来当且仅当 \(a_i \ge x\)。相当于和前面的过程没有关系。
于是可以暴力 DP,设 \(f_{i,j}\) 表示倒水到 \(i\) 时 \(i\) 内有 \(j\) 单位水的概率。转移非常的 trival。时间 \(O(n^3)\)。
将转移写成贡献的形式,前缀和即可 \(O(n^2)\),然后用线段树可以优化到 \(O(n \log n)\),DP 优化,很恐怖吧。
T2
场上什么也没观察出来,赛后好像发现了不少东西。
经过观察,发现合法方案的生成方式如下(有 \(i\) 这个数则 \(i\) 这一位是 \(1\),否则是 \(0\)):
-
将串复制 \(k\) 次。
-
将串复制 \(k\) 次,并将后面的 \(k-1\) 个副本变成全 \(0\)。
两种操作交替进行,直到串长变成 \(nm\),有 \(n\) 个 \(1\)。
这也代表我原来有 \((1,1)\),\((a,b)\) 表示串长为 \(b\),有 \(a\) 个 \(1\)。每一次我可以将 \((a,b)\) 变成 \((a,kb)\) 或者 \((ka,kb)\)。求方案数。
其实我们只要求出 \(n,m\) 分解成 \(i\) 个 \(> 1\) 的数的方案数,答案就可以轻松统计了。
于是乎我们要解决这样的子问题:
有 \(n\) 种球,第 \(i\) 种球有 \(a_i\) 个,每种球是相同的。
对于 \(m = 1 \sim \sum ai\) 求出将这些球放入 \(m\) 个不同的盒子中,且每个盒子非空的方案数。
一个方法是容斥,钦定一些位置为空。则有:
\(g_j\) 是不钦定非空的方案数,可以通过对出现次数根号分治 \(O(n\sqrt n)\) 求得。
上面那个式子卷积即可。时间复杂度 \(O(n\sqrt n + n \log n)\)。
T3
神秘科技。luogu P10364。
考虑倍增,现在已经知道答案 \(ans \bmod 2^k\) 的值,考虑求出 \(ans \bmod 2^{k+1}\) 的值。
设 \(x = ans \bmod 2^k\),则 \(ans \bmod 2^{k+1} = x\) 或 \(x + 2^k\)。两个都试一遍,如果 \(d(ans - x) \bmod (k+1) = 0\) 就可以认为他是 \(2^k\) 的倍数,如果有多个数满足条件就都保留下来,实际上状态数不会太多,最后得到 \(ans \bmod 2^{64}\),就是答案,询问次数在 \(500\) 左右。
Day 8
\(100 + 0 + 8\),\(\text{rk} 22\)。
被 T1 搞崩了,T2T3 根本没看。
T1
Luogu P12558。
钦定一些人赢,剩下的人输,判定合法可以用 Hall 定理,判断每个前缀和后缀是否合法即可。
考虑 DP,\(f_{i,j}\) 表示前 \(i\) 个人中,\(j\) 个人赢的方案数,但是这个东西只能判断前缀合法,不能判断后缀是否合法。
先不管这个,先枚举集合大小 \(i\),发现最弱的 \(i\) 个怪物一定匹配赢得那些,最强的 \(n-i\) 个匹配输的那些,也就是说在 \(> i\) 的部分我们根本不用考虑前缀的限制,\(< n-i\) 的部分根本不用考虑后缀的限制,前后缀分别 DP,拼起来即可。
T2,T3
不会。

浙公网安备 33010602011771号