2023.6.24 NOI模拟赛总结
1.时间安排
7:10~10:00
T1:感觉是简单DS,按套路拆成每个元素对每种长度的区间的贡献,写一写就得出来了拆分后的式子,大概是一个区间加等差数列的形式,还需要维护前驱后继。
T2:简单推了一下感觉是和团划分等难的问题,虽然补图传递闭包但是感觉用不上dilworth定理,很奇怪。
T3:看上去很经典的序列问题,但是取模很难处理,放到后面考虑。
先把T1的暴力式子写了,复杂度 \(O(n^2)\),可以过大样例。
一开始写的是用主席树维护前驱后继,区间加等差数列就用普通线段树,因为细节和空间问题调了很久,在9点终于过了所有大样例,运行时间不开O2大概是4s。
之后把主席树换成了set,已经可以跑到1.5s,开O2可以跑到800ms,但是怕大样例并不强,就想着继续卡一卡。
然后把线段树换成了标记永久化,可以跑到1.2s,开O2可以跑到700ms,之后换了zkw,但是效果不佳,就采用了这个版本。
10:00~11:00
看到这数据范围和时间限制之间分块,查询好说,实在是想不出来怎么根号维护修改,就直接暴力,用循环展开优化,时间可以跑到5s左右,开O2甚至只用800ms。
11:00~12:00
仍然没推出来补图传递闭包的作用,写了个暴力。
result:
T1:100 T2:10 T3:60
2.总结
T1:
这题的区间加等差数列实际上是关于下标的一次函数,于是可以开两个树状数组来把每个位置的答案维护成 \(kx+b\) 的形式,树状数组的常数就小的多,就不需要特别注意卡常的问题了。
T2:
不应该把图看成无向图的,看成可以传递闭包的有向图后,原问题实际上就是求偏序集的最小反链覆盖,那么根据dilworth定理就可以转化成最长链,于是如果串 \(a\) 是 \(b\) 的子串就从 \(a\) 向 \(b\) 连一个有向边,求最长链的长度。
暴力 \(n^2\) 是简单的,正解从本质不同的子串这个角度考虑,用sam的节点表示每个串,那么沿父亲边走相当于删除前面的若干字符,沿转移边走就相当于在后面加上一个字符,这个是符合偏序关系的,因为DFA的转移形成的图都是DAG,于是在广义SAM上做一个DAG最长链就可以了,复杂度 \(O(n)\)。
需要注意的是,看到无向图的团有时候也要注意本质上有可能是补图的反链,尤其在遇到最小团划分这类的问题。
T3:
序列分块做法是简单的。
针对取模这个问题,可以转化为修改是整块打标记,查询是求在这个整块中加上标记后大于模数的数字个数,这个可以通过排序后二分找到数量,于是只需要支持修改时整块区间打标记,散块暴力重构,查询时散块暴力枚举,整块在排序数组上二分。
设块长为 \(B\),修改是 \(O(BlogB+\frac{n}{B})\),查询是 \(O(\frac{nlogB}{B}+B)\),去 \(B=\sqrt(n)\),得到复杂度 \(O(n\sqrt(nlogn))\)。
用归并精细实现可以做到 \(O(n\sqrt(n+m))\),但是很麻烦,而且复杂度和值域相关。

浙公网安备 33010602011771号