2023SDPT-Round3
未整理完 Day1 Day3BC Day5 应该是摆了。
Day1
A
B
C
Day2
A
首先前缀和,然后离散化,记原序列为 \(a_i\),离散化后的前缀和数组为 \(s_i\),注意到原子序列区间和为 \(0\) 的位置即为 \(s\) 相等的位置,所以转化问题变为寻找一个区间最多的不相交的相等的 \(s\) 的数对,每个位置是可以重复使用的。记录前一个相同的位置为 \(pre_i\),将 \((i,pre_i + 1)\) 连边,得到一棵树。再将问题转化成从 \(l\) 开始跳几步能够跳到大于等于 \(r\) 的位置,最后这一部分可以树上离线,可以树剖,可以树上倍增。倍增貌似要以 \(4\) 为底,以 \(2\) 为底跳要被卡。于是做到线性空间。
B
手玩样例非常有劲,先钦定根为 \(r\),记选择的叶子为 \(u,v\),选择的最远点为 \(w\),则取 \(r\) 子树中深度排前三的叶子从深到浅为 \(a,b,c\),则答案必定为 \(w = a,u = b,v = c\),且 \(f(u,v) = c(a + b)\)。
换根 DP 求出每个点为 \(r\) 时子树中距离最远的叶子的距离,以及这种叶子的个数。一边计数可以一边算出 \(u,v,w\) 的备选方案数量,分讨深度等于关系即可。
C
还得是 dwt,全场唯二有分。
看起来很贪或者很有规律,实则一点劲没有。比较现实的做法是随,直接调用 checker 判随出来的解对不对。这样 \(N = 4\) 还挺快,到 \(N = 5\) 都虽不出来。考虑随机调整,每次从不合法的小的那一部分里面随机改几个,然后接着判对不对。这样的话能一路打到 \(N \leq 14\),加上打表可以拿七十多分(学到什么叫做可见字符打表)。
正解是将所有状态都列出来,每个状态拆成两个点,记为 \(X^{0}\) 和 \(X^{1}\),假设说两个状态 \(X\) 和 \(Y\) 只有第 \(d\) 位不同,其中 \(X_d = 0\),\(Y_d = 1\),则连单向边 \((X^{0},Y^{1})\)。观察性质,入度即为在这个状态下 \(d\) 这个人选什么颜色,要保证每种状态下都能又一半下取整的正确率,这个时候要想到欧拉回路(很神的地方)。如果 \(N\) 为偶数的话,每个点入度都等于出度,直接就做完了;如果是奇数个点的话,注意到下取整的限制,所以也是好做的,建立虚点向单出来的那个状态连边即可。最后跑欧拉回路,可以隐式建图。
Day3
A
手玩可以猜出结论,最优方案一定是对着一个点反复操作。非常好写,flood-fill 分出层数,最优操作次数即为最大层数的最小值,地图足够小对着每个连通块暴力判断就行,需要注意连边不能连到 x
上。时间复杂度 \(\mathcal O((nm)^2)\)。
证明可以考虑记 \(D_i\) 为 \(i\) 这个连通块在任意操作某连通块构成的操作顺序图中层数最大层数的最小值,每次操作只能使 \(D_i\) 最多减少 \(1\),从最短路方面考虑。
B
C
如果全部都是偶数,答案必定有解,策略是根据每个数除以二之后的奇偶性分成两组,每组内部先合并,容易发现合并后会交换所属组。这样反复操作最后如果剩下也是两个组各剩一个,而他们都是偶数一定可以合并,所以一定有解。
推广到一般情况,按照模 \(4\) 意义下不同的余数分成四个集合 \(S_0,S_1,S_2,S_3\)。
- 如果 \(|S_0| \geq 1 \wedge |S_2| \geq 1\),则必定有解。取 \(x_0 \in S_0,x_2 \in S_2\),操作剩下的数使得剩下不超过两个元素 \(y,z\);
- 只剩一个元素 \(y = 2k\),随便做;
- 只剩一个元素 \(y = 2k + 1\),操作 \(x_0\) 和 \(x_2\) 得到一个奇数 \(x'\),操作 \(x'\) 和 \(y\);
Day4
A
基环树。记树边最小值为 \(a\),环边最小值为 \(b\),(非严格)次小值为 \(c\),则答案为 \(\min(a,b+c)\)。二分答案 \(mid\),计算使得 \(a \geq mid \wedge b + c \geq mid\) 的次数并与 \(z\) 比较看是否合法。
树边是好做的,直接都放到一个 BIT 里头查前缀和即可。对于 \(b + c\) 做分类讨论,如果 \(b + c \geq mid\) 则操作次数为 \(0\);如果 \(2c \geq mid > b + c\),则操作 \(mid - b - c\) 次;如果 \(2c < mid\),则操作次数为 \(\lceil \dfrac{mid}{2} \rceil\)。可以使用 multiset 维护所有的 \(a,b,c\),但是常数过大且复杂度为 \(\mathcal O(n \log n \log z)\)。注意到树状数组的特殊结构,可以直接在树状数组上二分,这样做到 \(\mathcal O(n \log n)\)。
B
首先区间肯定是个幌子,每条边要么取到上界,要么取到下界。比较显然的贪心想法是钦定路线上的边都取下界,其他边都取上界,然后跑 dijkstra 判答案。但当另一条可能存在的最短路与钦定路线部分重合时这部分边是不好定值的。
先二分答案,二分钦定路线最远能到第几条边为最短路。不妨一边 dijkstra 一边给边定值。将 \(1\) 作为普通的起点 \(A\),此时它的距离为 \(0\);二分出来的路线到达的点为 \(B\),此时它的距离为前面选定路线的边取 \(l\) 值的和。将二者都放入队列中跑 dij,如果一个位置被 \(A\) 所扩展,那么扩展过来的边就选择 \(r\),否则即为被 \(B\) 所扩展,扩展过来的边就选择 \(l\)。如果存在距离相同的情况,即 \(A\) 和 \(B\) 同时扩展到了一个位置,那么后面的路肯定是二者一块走,所以优先判定为 \(B\) 扩展而来。最后只需要判断 \(n\) 点是由谁扩展而来,如果是 \(B\) 则证明可行,否则则证明不可行,相应的二分就好了。时间复杂度 \(\mathcal O((m + n) \log^2 m)\)。
C
用四元组 \((a,b,c,d)\) 刻画一个人的移动范围,\((b,c)\) 为正常的运动范围,去掉左侧的一条竖线后移动范围变为 \((a,c)\),同理去掉右侧的一条竖线变为 \((b,d)\)。可以手动在值域的上下界添一条竖线,这样能够保证每个人都有 \(a,d\)。
第一步求出所有本质不同的四元组。先按 \(y\) 坐标做扫描线,维护当前横线与所有竖线的交点构成的 set,那么一个四元组就是 set 中连续的四个数,在每次插入和删除能轻松地得到新的四元组,注意要先都插入删除完再统计四元组。能够证明本质不同的四元组的个数是 \(\mathcal O(n)\) 量级的。
第二步用 DP 来统计答案。对于两个四元组 \((a_1,b_1,c_1,d_1)\) 和 \((a_2,b_2,c_2,d_2)\) 其中 \(a_1 < a_2\),能够被同时选择,当且仅当 \(a_2 \geq c_1,d_1 \leq b_2\),于是根据这个可以得出同时选择是具有传递性的。对于四元组做一个从左向右的扫描线,扫到 \(c_1\) 在 \(d_1\) 处插入 DP 值,扫到 \(a_2\) 在 \(b_2\) 处查询得到 DP 值。这样两次扫描线用树状数组和 set 做到 \(\mathcal O(n \log n)\)。
Day5
A
B
C
Day6
A
暴力 DP 直接 \(f_{i,j}\) 表示前 \(i\) 个数划分为 \(j\) 段的最大答案,转移枚举最后一段的开头,能够发现区间贡献只会变化 \(\mathcal O(\log a)\) 次,并且区间长度越长,贡献只会不减,转移点只会在区间贡献变化的位置,于是做到 \(\mathcal O(nk \log a)\),这样就可以拿到 60 pts。
大胆观察 DP 值可以猜测出 \(f_{n,k}\) 关于 \(k\) 是凸函数,上 WQS 二分可以做到 \(\mathcal O(n \log k \log a)\)。
B
很牛啊,退火可以过,乱搞爆搜也可以过。套壳官方 sol 学习一下。
记 \(s_i\) 为第 \(i\) 个元素是否选择,\(t_{i,j}\) 为第 \(i,j\) 个元素是否同时选择,于是题目式子化为:
右边是一个 \(n^2\) 个变量的 01 分数规划,套路的二分答案,转化为:
这个式子的意义为有 \(n^2\) 个物品,选了 \(t_{i,j}\) 则必须选 \(t_{i,i}\) 和 \(t_{j,j}\),选了 \(t_{i,j}\) 有 \(w_i w_j\) 的贡献,选了 \(t_{i,i}\) 有 \(- w_i^2 \times ans\) 的代价,还有一些钦定选了 \(t_{x,x}\) 必须选 \(t_{y,y}\),问是否有一种方法使得选出来总收获为正数。这是最大权闭合子图模型,网络流即可,时间复杂度 \(\mathcal O(n^4)\)。
C
巨大困难题,完全不会做,贺题解了:
利用期望线性性,考虑对每一个 \(i\),它请求组队成功的概率是多少。考虑 \(i\) 成功的充要条件是什么,首先特判 \(a_i = i\) 的情况,然后显然 \(a_i\) 在排列中的位置要在 \(i\) 的左边,同时令 \(b_x\) 表示 \(a_u = x\) 的 \(u\) 的集合,那么排列中 \(a_i\) 到 \(i\) 这段区间中不能出现 \(b_{a_i}\) 中的元素。上述条件都是必要的,但并不是充分的,因为 \(a_i\) 也可以组队成功,也就是要将上述概率减去满足上述条件且 \(a_i\) 组队成功的概率。这个形式和上面求的东西非常相似,考虑从 \(i\) 开始不断跳 \(a_i\) 得到的序列,形如 \(x0 = i, x_1, x_2, . . . , x_c, x_{c+1}, . . . , x_d(a_{x_d} = x_c)\),也就是一个类似 \(\rho\) 的结构。于是问题转化为了:求有多少长度为 \(n\) 的排列满足 \(x_0,x_1, . . . , x_k\) 在其中的出现位置依次递增,且 \([x_i,x_i+1]\) 中不能出现 \(b_{x_i}\) 中的元素。
注意到一个重要的性质:所有集合 \(b_{x_i} / x_{i−1}\) 不包含 \(x\) 序列中的值且两两无交,特别地可能有 \(i = c, x_d \in b_{x_c}\),这个特殊处理。于是可以发现答案只与 \(b_i\) 的大小有关。直接 DP 还是不好做,于是考虑容斥,令 \(f_{i,j}\) 表示考虑到了 \(i\) 这个前缀,目前钦定有 \(j\) 个 \(b_x\) 中的元素位置不合法的排列数,转移只需要枚举下一个间隔中不合法的数量后乘上组合数即可,时间复杂度 \(\mathcal O(n^3)\)。注意到需要特判 \(i = c, x_d \in b_{x_c}\),于是在 \(i > c\) 后将 \(|b_{x_c}|\) 减一后再重做一遍 DP 即可。时间复杂度 \(\mathcal O(n^4)\)。
注意到上述 DP 的 \(\sum |b_i| \leq n\),这等同于在一个链上做树上背包,故将背包大小的限制缩进即可将 DP 复杂度优化至 \(\mathcal O(n^2)\),总时间复杂度 \(\mathcal O(n^3)\)。
Day7
A
使括号序列修改(左变右,右变左,保证序列长度为偶数)为合法的最小次数:设 \(( = -1,) = 1\),定义 \(pr\) 为前缀最大值,\(sf\) 为后缀最小值,那么一个区间的答案为 \(\lceil pr/2 \rceil + \lceil |sf/2| \rceil\)。
区间 reverse 是难维护的,直接把线段树摁死了,所以平衡树维护。要维护前缀最大值和后缀最小值,可以转化成维护前缀最大值和区间和减后缀最大值,这样就是维护最大前后缀和以及区间和。注意 replace 的操作优先级高于 reverse 和 inverse 即可。容易做到 \(\mathcal O(n \log n)\)。
B
神秘交互。
如果这个图是好的,那么称选择的那个 \(\deg =1\) 的点为头,\(\deg =2\) 的那个点为身,\(\deg = n-2\) 的那个点为尾,其它点为叶子。
先随便选个点花 \(n\) 次查一下,拿到邻居集 \(S\)、非邻居集 \(T\) 和度数 \(d\)。 接下来讨论一下:
- \(d=0\):
report(0)
; - \(d=n-2\): 它是尾,那么只有头和它不相连,拿到头之后花 \(n\) 次查一下头是不是有唯一邻居,再花 \(n\) 次检查一下这个唯一邻居的度数是不是 \(2\) 即可;
- \(d=1\): 有两种可能:是叶子或者头。花 \(n\) 次查一下唯一的那个邻居的度数,应该只有两种可能,\(2\) 或者 \(n-2\),否则
report(0)
。- 如果是 \(2\),那就再花 \(n\) 次查一下那个邻居,应该得到一个度数 \(n-2\) 的,这时候
report(1)
,否则report(0)
; - 如果是 \(n-2\),那么调用已经提到的 \(d=n-2\) 的做法。
- 如果是 \(2\),那就再花 \(n\) 次查一下那个邻居,应该得到一个度数 \(n-2\) 的,这时候
- \(d=2\):有两种可能,是叶子或者身。花 \(2n\) 次查一下两个邻居的度数,里面应该刚好有一个度数 \(n-2\) 的,之后调用已经提到过的做法;
- \(d\in [3,n-3]\): 困难的部分,表明它是一个叶子。想办法识别出一个具有前面提到的几种度数的点。使用以下观察:头和身在 \(T\) 里,尾在 \(S\) 里,且头与 \(S\) 里的所有点都不相连,尾与 \(T\) 里除了头的点都相连,且满足其中任何一个性质的点有且仅有一个。这样就有以下的算法:随便选一个 \(u\in S,v\in T\) 查一下 \((u,v)\),那么如果:
- 有边,识别出 \(v\) 不是头;
- 没有边,再选一个 \(v'\neq v\in T\) 查一下 \((u,v')\)。接下来如果;
- 有边,识别出 \(v'\) 不是头;
- 没有边,识别出 \(u\) 不是尾;
- 也就是说,可以用 \(2\) 次询问删掉一个 \(S\) 或者 \(T\) 里的点。重复以上过程直到 \(|S|=1\) 或者 \(|T|=1\),于是就用不超过 \(2n\) 次询问拿到了一个特殊点。再花 \(n\) 次检查一下这个点是不是确实满足对应的性质,之后调用前面的特殊情况即可,大概要稍作调整。
C
论文题,开摆。TBC:海草。