思路
先把赛时的思路搬一下
你发现确定两个人的起始点, 其实是可以确定 \(\rm{Alice}\) 的选点可能的, 考虑写个代码验证一下
具体的, 就是分成两个弧, \(\rm{Alice}\) 可以选择一个弧的优势(过半), 然后其他的劣势
感觉现在是猜结论, 全靠感性, 我也不知道怎么解释这个问题
那么这样枚举两个起始点, 好像是 \(\mathcal{O} (n^2)\) 的?
具体的
- 两边都是奇数个 : 可以选择两种方式, 选取一边的超过一半和另外一边的少于一半
- 两边都是偶数个 : 唯一情况分一半
- 一奇一偶 : 唯一情况多吃一点
所以这样子打下来, 可以知道 \(\rm{Alice}\) 确定唯一占领时, \(\rm{Bob}\) 怎么选才能最大化自己, 然后就知道答案了
做到 \(\mathcal{O} (n^2)\) 唯一需要的是考虑环上的和怎么快速计算
首先是枚举两个分割点
如何把两边分开 : 断环为链拷两遍
如何计算和 : 前缀和
如何快速计算分一半 : 计算编号之差
我们细致一点方便写代码:
首先读入这个环的时候就将其断开复制两遍
枚举 \(\rm{Alice}\) 的起手点 ( \(\rm{subtask} \ 3\) 直接钦定为 \(1\) ), 对于这个点我们枚举 \(\rm{Bob}\) 的所有起手点, 然后我们可以找到这个起手点的两个位置, 显然的根据上面的分类讨论
- 两边都是奇数个 : 可以选择两种方式, 选取一边的超过一半和另外一边的少于一半
- 两边都是偶数个 : 唯一情况分一半
- 一奇一偶 : 唯一情况多吃一点
还有一个问题 : 如何在链上找到两个起手点
其实很简单, 假设两个起手点 \(u < v\) , 直接找到 \(v\) 第二遍复制的位置即可
然后检查答案即可
注意同 \(\rm{Alice}\) 起手点之间取 \(\min\) , 不同之间取 \(\max\)
考虑优化到可接受的时间复杂度
因为你枚举 \(\rm{Alice}\) 的起手点已经 \(\mathcal{O} (n)\) 了, 那么你找到 \(\rm{Bob}\) 的起手点使得答案取 \(\min\) 一定要做到 \(\mathcal{O} (1)\)
这个看起来非常不可能啊, 但是实际上如果你更加理性是想得到的
考虑 \(\rm{Alice}\) 选择起手点之后, \(\rm{Bob}\) 能够做到怎样限制 \(\rm{Alice}\) 的选段
还是考虑上面的这些性质, 放到整体上来做
对于 \(\rm{Alice}\) 的一个起手点, 事实上我们可以找到 \(\lceil \frac{n}{2} \rceil\) 个连续的弧, 对于 \(\rm{Bob}\) 的所有起手点选择, 其实一定可以将其限制到这 \(\lceil \frac{n}{2} \rceil\) 个连续的弧中弧内和最小的一个, 具体的, 按照上面的规则反推即可
问题简化为, 对于每个点 \(i\) , 找到覆盖 \(i\) 的所有长度为 \(\lceil \frac{n}{2} \rceil\) 的弧中, 弧内和最小的一个
怎么解决?
可以预处理出所有长度为 \(\lceil \frac{n}{2} \rceil\) 的弧长, 然后队列维护即可, 不困难
对于枚举的所有点, 我们单调队列处理弧的情况, \(\rm{belike}\) :
但是你发现这和普通的队列枚举并不太相同, 即到了后面会加入最初被删除的线段
类似于断环为链, 事实上我们可以拷贝两份弧, 仅仅需要 \(\mathcal{O}(n)\) 的空间
考虑怎么维护这种神秘玩意, 你注意到就是一个滑动窗口, 那岂不是无敌了
当然你优先队列直接做应该更简单吧
实现
框架
我们细致一点方便写代码:
首先断环为链, 复制一份接到后面
然后跑弧长, 然后跑优先队列优化
代码
不打算这么困的时候挑战我的码力了
总结
这个题不给 \(\rm{subtask \ 3}\) 我可能会直接搞到正解, 也有可能一分不得???
暴力算法的优化往往需要更整体的思考
不行打表找规律