Romanian Master of Informatics 2020 题解

罗马尼亚大师赛。

感觉题目挺有趣的。

Link

Editorial

Results

Day 1

A \(\color{green}\bigstar\)

通信,要询问区间最大值,那么压缩笛卡尔树即可。

考虑笛卡尔树的建树过程,加入点就加入一个 1,删除就放一个 0,就可以还原了。

一颗二叉树都可以这样压缩。

想了一下其他压缩方式,设 \(s_{l,r}\) 表示区间 \([l,r]\) 压缩出的串,那么设 \(t\) 表示区间最大值。

\[s_{l,r}=(s_{l,t-1})s_{t+1,r} \]

这样也唯一对应括号序列。

B \(\color{Gold}\bigstar\)

有很多比较阴间的 bitset、FFT 做法,但是正解很高妙。

先观察一下变换的性质,设 \(f_{i,k}\) 表示 \(i\) ,在位数为 \(k\) 的时候进行翻转得到的东西是什么。

可以得到 \(f_{i,k+1}=2f_{i,k},f_{i+2^{k},k+1}=2f_{i,k}+1\)

考虑哈希。

朴素的一个区间的哈希就是 \(\sum B^{n-i}a_i\)\(B\) 是一个常数。

套在这个上面,发现就是把 \(f_{i,k}\) 的每一个 \(B^i\) 变成 \(B^{2i}\),然后后面的多乘一个 \(B\)

直接维护平方很不好维护,此时很妙的一手是开始设置一个 \(P=B^{2^c}\),开始先让所有 \(f_{i,0}\) 乘上 \(P\),然后每次转移只需要把 \(P\) 开个根号,这样就可以支持两个合并了。

那么同理,前面的前缀和预处理也要对每个空隙大小跑一遍,然后就可以判断了。

复杂度 \(O(n\log n)\)

C \(\color{Gold}\bigstar\)

高妙数据结构科技。

首先 \(O(n\log n)\) 有若干做法,不说了。

然后注意到维护这个 dp,要维护一个前面删除,后面加入删除,还要支持全局查询最小值。

很牛的一个科技是双栈模拟,每个栈记录一个前缀最小值,然后直接合并。

一个栈如果弹空了,那么把另一个栈分一半过来。

复杂度分析的话记录势能为两个栈大小的绝对值,复杂度就是 \(O(n)\)

Day 2

A \(\color{blue}\bigstar\)

空间 20mb。。。

显然建个树,然后跑个祖先。

一开始写了个 dfs ,然后栈上二分,MLE。

学习了空间复杂度 \(O(n)\) 的树上倍增,有点太牛了。

就是如果大跳两步距离一样就合并,证明一下复杂度是对的,严格吊打树剖。

posted @ 2023-10-24 20:10  houzhiyuan  阅读(22)  评论(0编辑  收藏  举报