UOJ Logo EntropyIncreaser的博客

博客

EI Round #1 题解

2018-06-08 18:01:17 By EntropyIncreaser

本次部分选手的成绩存在争议,请自重。我知道共同学习的同学确实会被培养出相似的思维模式,但是这次的提交时间之密集程度我认为超过了“同一种思维模式”可能达到的程度。

T1 狗

考察选手对集合的理解以及基本的聚合分析能力。

其实这道题和讲课的那道题是完全不同的,那道是选两个求交……

算法 1

我会 $\Theta(nq^2)$ 暴力!

预计得分 12 pts.

算法 2

考虑如何快速查询某个元素是否在这个区间里都有。

维护并查集,插入一个元素时如果左右有这一元素,就将其左右合并,维护每个并查集的最左和最右。

时间复杂度 $\Theta(nq + |S|)$ (对于此特殊应用,不带 $\alpha$ 常数)

预计得分 30 pts.

算法 3

考虑在插入单个元素时候对答案的影响,如果把元素插入到 $x$ 处,联系算法 2 我们可以想到,这使得 $l \in [l_{dsu}, x], r \in [x, r_{dsu}]$ 处的答案都 + 1 ,用一颗动态开点的树状数组套线段树即可维护。

当然,这里不能用真正的并查集,因为空间开不下,可以用 $\texttt{set}$ 等维护。

时间复杂度 $\Theta((|S| + q)\log^2 n)$

预计得分 50 pts.

算法 4

基于算法 3 ,对于一段空区间插入元素,可以变通一下,对于所有 $l, r \in [l_x, r_x]$ 的贡献都 +1 。而我们仍然暴力合并,每个原有区间实际上只会被用来合并两次:左一次、右一次。故一次区间修改引发的合并次数是均摊 $\Theta(1)$ 的。

时间复杂度 $\Theta(q\log^2 n)$

空间复杂度 $\Theta(q \log^2 n)$

预计得分 78 pts. ~ 100 pts.

算法 5 (std)

上面这个算法常数略大,而且空间略危险,所以我们考虑先将操作存下来,然后用离线树状数组来实现这个东西,跑得效果简直就像一个 $\log$。

空间复杂度就降到 $\Theta(q\log n)$ 辣!

预计得分 100 pts.

后记:很不幸这道题和前段时间 Codeforces 的一道题中解题思路有所共同,所以做过那道题的人可能想这道题就秒出答案了……然而其实我是先出题后来才打那场比赛的……

为什么会这样呢……明明是我先来的,第一次有了开比赛的打算,又有了好的题目点子,两件快乐事情重合在一起。而这两份快乐,又给我带来更多的快乐。但是,为什么会变成这样呢……我的 OI 怎么就白学了呢……

T2 梨

考察选手对数据结构优化建图的能力。

其实吧,这道题重点只想考察一个优化方法……而且我出完这道题后才发现和 POI 撞了,就当给大家送温暖了……

算法 1

对每个供应商连出 $k_i$ 条边,这些边的费用是 0。对每个原点到供应商的连边,有流的上限 $t_i$ 和费用,而对每天拆点,有下界。跑最小费用可行流

时间复杂度 $\mathrm{MinimumCostFlow}(|V| = \Theta(n + m), |E| = \Theta \left(\sum k_i \right))$

预计得分 45 pts.

算法 2 (std)

考虑优化一些连边。

考虑到供应商仅仅是对一个区间的点连边,我们考虑额外建立一些虚点。

一个方法是造一颗线段树,然后每个供应商只需要连出 $\Theta(\log n)$ 条边啦!

时间复杂度 $\mathrm{MinimumCostFlow}(|V| = \Theta(n + m), |E| = \Theta(n + m\log n))$

当然,你也可以通过 ST 表的形式来维护,那就是 $\mathrm{MinimumCostFlow}(|V| = \Theta(n\log n + m), |E| = \Theta(n\log n + m))$

预计得分 100 pts.

T3 锅

考察选手对傅里叶变换的基本认识,对分治思想的基本理解,对“将执行过程作数据化处理”的推广能力,对分块法的基本掌握。

算法 1

对于每次修改,只考虑本修改对 FFT 后的数组的影响

算法 2

对每次查询,暴力执行过程。

前两种算法并用 $\Theta((q_{\min} + \log n)n)$,预计得分 22 pts.

56 pts. 这个档嘛……就是一个分档,如果暴力写的太强或者正解写的常数太大就是这个分……

算法 3 (因为常数优秀所以成了 std)

考虑对时间进行分块。

设时间块大小 $b$,我们每过 $b$ 次修改就将新的系数数组重新做一遍 FFT ,每次查询对于未纳入 FFT 的修改暴力计算对答案的影响。

发现时间是 $\Theta \left(n\log n \cdot \frac q b + qb\right)$ ,取 $b = \sqrt{n\log n}$ 有复杂度 $\Theta \left(q\sqrt{n \log n} + n\log n\right)$

预计得分 100 pts. ,因为它的常数足够优秀,但是为了追求理性的愉悦,本题原本应该的 std 是接下来这种方法:

算法 4 (废弃的 std)

类比线段树等数据结构,考虑对 FFT 算法的执行流程用数据结构记录下来,

回顾按奇偶性分治,我们可以将二进制数位的逆序建出一颗 01-Trie,但是查值仍然要递归到两个子节点,复杂度似乎没有改善。

考虑我们有上面的两种暴力:

暴力 1 是修改线性,查询立刻的。

暴力 2 是修改立刻,查询线性的。

当子树大小达到了阈值 $2^b$,我们对它使用暴力 1 ,对于不到的时候我们进行分治,此时类似暴力 2 。

这样我们的修改在树上只是走到一个截止的大叶子上然后进行修改,时间 $\Theta\left(2^b\right)$。

我们的查询在树上则要覆盖一些区间,但到叶节点的查询就是立即的,时间 $\Theta \left(2^{k - b}\right)$。

当然,你并不必要真的把这棵树显式地构建出来,另一种理解方法是它在进行一个截半的蝴蝶操作,写起来应该是可以像数列分块一样的。

令 $b = \frac k 2$, $2^b = \sqrt n$ ,时间复杂度 $\Theta(q \sqrt n + n\log n)$ ,预计得分 100 pts.

这个做法可能是我写的常数太大,虽然也能通过,但是跑得反而比按时分块要慢,有哪位哥哥写一个优雅还跑得快的版本呀?

算法 ???

如果你有复杂度优于出题者的算法,欢迎在讨论区发表,出题人十分期望见到 $O(\operatorname{poly} \log n)$ 每次修改的做法。

评论

newbiedmy
T3 算法2考试通过终测被卡 这也太看脸了吧 题目毫无思维难度,就是常数round吧 (我没AK,我一定要D出题人)
newbiedmy
T3手动O3就过了。。。
newbiedmy
我们来想一个T3的更优做法吧 出道新题把现在所有AC代码都卡T[奸笑]
oscar
T1本质看起来像二维数点啊。。 只需要对于每个权值维护存在这个权值的极长区间[l,r],然后cdq分治/树套树查询ql>=l&&qr<=r的区间个数即可(我貌似没看懂题解啊qwq) 维护区间可以拿q个set
fpdqwq
我t1写了4个小时啊 还没写对 你们是怎么做到写的那么快的
Hineven
/捂脸
EntropyIncreaser
我是不是比较适合出 Div. 3 难度的那种啊qwq
hehelego
(去年置顶至今

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。