20231018
20231018 NOIP#23总结
时间安排
7:50~8:20
看题,\(A,B,D\) 会一档,\(C\) 不会。
8:20~8:40
写 \(A,B\) 的第一档
8:40~9:10
\(A\) 突然想了个贪心策略不知道正确性,反正打了分段写上吧。
9:10~9:40
写 \(D\) 的第一档,想了想后面的不会。
9:40~10:50
推了半天 \(B\) 的式子,终于推出来了写了。
10:50~11:50
树剖乱搞 \(C\) 题
题解
A.贪心
但是我赛场的贪心不对。/jk
正确的贪心策略是,将序列从小到大排序,选取的一定是一整个后缀。于是就可以枚举选取到哪个位置,总复杂度 \(O(n)\)。
B.数学
题目给的式子很好看,就是复杂度不好看,考虑化简。
发现式子的前两个循环是枚举子区间,后面都是形如 \(a_i\times b_j\) 的形式,包含它们的区间必须满足 \(l\in[1,\min(i,j)]\) 且 \(r\in[\max(i,j),n]\),所以每个会出现 \(\min(i,j)\times (n-\max(i,j)+1)\) 次。
根据这个式子,维护 \(c_i=a_i\times i\ \ \ d_i=a_i\times (n-i+1)\) 并做前缀和,\(f_i=(n-i+1)\sum_{j=1}^i c_j+i\sum_{j=i+1}^n d_j\) 并做前缀和。则上述答案可以在 \(O(n)\) 复杂度内求得。
考虑修改,设上次的答案为 \(sta\),则修改后的答案 \(ans=sta+k\sum_{i=l}^r f_i\),可以 \(O(1)\) 回答。总复杂度 \(O(n+q)\)
C.~
显然的是一个边在全排列中经过的次数就是删掉这条边后两棵子树中关键点的个数相乘,这个可以一遍树形 \(DP\) 解决。
考虑修改,通计每个点直接相连的边经过次数的总和,将总代价加上这个乘“魔法强度”即可,每次除 \(n!\) 输出。
D.根号分治+序列分块
考虑对于模数 \(x\) 进行根号分治,设分治中心为 \(M\)。
修改时:
\(x\leq M\):暴力统计 \(s[x][i]\) 表示在模 \(x\) 意义下结果为 \(i\) 的位置的增量,并统计前缀和,每次修改是 \(O(M)\) 的。
\(x>M\):整个序列最多被分成 \(\frac{n}{M}\) 段。如果用类似线段树对每段进行区间修改,则修改复杂度为 \(O(\frac{n}{M}\log n)\),询问复杂度为 \(O(\log n)\),操作复杂度极不平衡。为了平衡复杂度,可以用分块维护(块长为 \(B\)),需要维护块内的差分数组和块间标记的差分数组,则修改和询问复杂度都是 \(O(\frac{n}{M}+B)\)
查询时:
答案为原序列的总和 \(+\) \(x\leq M\) 的增量 \(+\) \(x>M\) 的增量。
原序列的总和可以直接用前缀和维护。
\(x\leq M\) 的增量可以暴力枚举每一个 \(\leq M\) 的模数,对于每一个模数用 \(s\) 数组的前缀和 \(O(1)\) 统计,总复杂度 \(O(M)\)。
当 \(x>M\) 时,设 \(c_i\) 为差分数组,\([l,r]\) 内的数值和为 \(\sum_{i=l}^r\sum_{j=l}^i c_j=(r-l+1)\sum_{i=1}^{l-1}c_i+\sum_{i=l}^r c_i\times(r-i+1)\)。对于这个式子的第一部分,暴力做前缀和即可。对于第二部分,把它拆成 \((r+1)\sum_{i=l}^r c_i-\sum_{i=l}^r c_i\times i\),用类似区间操作的树状数组维护 \(c_i\) 和 \(c_i\times i\) 的值即可,总复杂度 \(O(\frac{n}{B}+B)\)
取 \(M=B=\sqrt n\),总复杂度 \(O(n\sqrt n)\) 级别。