CSP模拟赛 #37
A
题意:给定 \(n, a_{1\sim n}, b_{1\sim n}\),两个点 \(i,j\) 之间有连边当且仅当 \(a_i - a_j\le i - j \le b_i - b_j\) 或 \(a_j - a_i\le j - i\le b_j - b_i\),求图中连通块数量。
\(1\le n\le 10^6\)
考虑条件 \(a_i - a_j\le i - j \le b_i - b_j\) 相当于 \(a_i - i\le a_j - j\) 并且 \(i - b_i\le j - b_j\)。
令 \(x_i = a_i - i,\ y_i = b_i - i\),那么满足 \(x_i\le x_j\) 且 \(y_i\le y_j\) 的两个点 \(i, j\) 连边。
将所有点按 \(x_i\) 从小到大排序,用一个栈表示目前所有连通块的最小的 \(y\) 值,每次加入一个点更新即可。
B
题意:平面上有 \(n\) 个点,请你确定 \(k\) 条互相平行的直线,满足每个点至少在一条直线上,并且每条直线上至少有 \(2\) 个点。数据保证至少有一个解。
\(2\le n\le 4\times 10^4, \ 1\le k\le \min(50, \frac n2)\)
鸽巢原理,考虑前 \(k + 1\) 个点至少有两个点被分配到同一条直线上。枚举这两个点,即可确定直线的斜率,然后 \(\mathcal O(n)\) 判定,时间 \(\mathcal O(nk^2)\)。
有更优的做法。考虑处理出这 \(n\) 个的上 / 下凸包,那么直线的斜率一定取自于凸包上相邻两点的斜率,这样只需要枚举 \(\mathcal O(k)\) 次了。
C
题意:给定 \(n\),计数有多少个严格单调递增,值域在 \([1, 2^n)\) 的序列 \((a_1, a_2, \dots, a_m)\) 满足不存在位置 \(i(1\le i\le m - 2)\) 满足 \(a_i \oplus a_{i + 1} \oplus a_{i + 2} \not = 0\),答案对 \(998244353\) 取模。
\(1\le n\le 2\times 10^7\)
考虑按第 \(n - 1\) 位来分类。第 \(n - 1\) 位为 \(1\) 的数一定满足条件,第 \(n - 1\) 位为 \(0\) 的数可以划分子问题,所以可以按分界线处来容斥。
设 \(f_i\) 表示位数为 \(0 \dots i\) 且最后一个数的第 \(i\) 位为 \(1\) 的方案数,总方案数为 \(f_{i - 1}\cdot (2^{2^i} - 1)\)。
枚举 \(j\) 表示最后一个第 \(i\) 位为 \(0\) 的数的最高位。钦定该数以及第 \(i\) 位为 \(1\) 的前两个数异或和为 \(0\),那么不论第一个数以及第三个数取什么,第二个数总有唯一的一个取值。为了满足第二个数小于第三个数,应要求第三个数的第 \(j\) 位也为 \(1\)。那么方案数为 \(f_j\cdot \sum\limits_{x = 0} ^ {2^i - 1} [x\text{ 的第 } j \text{ 位为 } 1] 2^{2^i - 1 - x}\)。设求和式答案为 \(d\),那么有 \((2^{2^j} + 1) d = 2^{2^i} - 1\),解得 \(d = \dfrac {2^{2^i} - 1} {2^{2^j} + 1}\)。前缀和优化可以做到 \(\mathcal O(n\log n)\)。
考虑线性,发现瓶颈在于求逆元,发现 \(2\) 不是原根,其次幂在模 \(998244353\) 意义下只有 \(24\) 个值,记忆化即可。
D
题意:给定一棵树,每个点有点权 \(b_u\) 和点权每天增加的值 \(a_u\)。你需要处理 \(q\) 次事件,每次要么给出 \(u, v, w\),其中 \((u,v)\) 为一条边,令 \(a_u\gets a_u + w, \ a_v \gets a_v - w\),要么询问某一天在整棵树上选一点 \(u\),求 \(\min\limits_u\{\sum\limits_v \text{dist} (u,v) \cdot b_v'\}\),其中 \(b_v'\) 为当天的点权。
\(1\le n, q\le 10^6\)
拆贡献,考虑每条边的贡献,是子树内点权和与子树外点权和的最小值。
我们可以维护两个一次函数表示子树内和子树外的点权和,将他们的相交的时间扔进 set 中。
考虑修改,每次只会影响一条边,将其从 set 中删掉,更新后重新扔进 set 即可,时间复杂度 \(\mathcal O((n + q)\log n)\)。