Codeforces 1706 D,E

D
枚举max,让min最大

假设当前max=v,于是对于0ai<v+1的数,pi=1

那么对于v+1ai<2(v+1)的数,首先pi2(否则最大值就不是v了),并且我们想让最小值大,故我们取pi=2

我们可以推广:

(t1)(v+1)ait(v+1),那么我们最优的方案是pi=t

故我们将数列分成若干块——[0,v+1),[v+1,2(v+1)),[2(v+1),3(v+1)),...,对于每一块,我们要找到aip的最小值。由于同一区间内p相等,故这个最小值一定是区间内最小的a除以p的值。

我们用st表维护区间最小值,对于枚举的max=v,我们同时暴力枚举每个区间,由于调和级数i=2n1i=logn,这样时间复杂度为O(nlogn)

E
l,r内部的点对两两可达,那么意味着:

(l,l+1),(l,l+2),...(l,r)(l+1,l+2),(l+1,l+3),...,(l+1,r)...(r1,r)

这些点对两两可达。

那么我们可以去掉一些无关的点对。我们发现,如果(l,l+1),(l+1,l+2),...,(r1,r)(rl)个点对是两两可达的,那么其余的点对就一定两两可达。

故我们设f(i)=ii+1,回答询问时只要回答f(l),f(l+1),...f(r1)的最大值即可,这个可以用st表实现。(怎么又是st表啊)(这个求法很像后缀数组求lcp的过程)

那么原本我们有O(n2)个不同的点对,现在只有O(n)个了,我们分别求f(1),f(2),...,f(n1)的值。

如何快速求出呢?首先按顺序考虑边,如果当前加入的边(u,v)在图上已经联通,那么就不必加上了,否则我们就加上这条边。(类似于kruskal算法流程,用并查集实现)

容易发现求出的是最小生成树,那么对于询问(i,i+1),我们相当于查询树上从i(i+1)路径中最大的边权。这个可以用倍增实现。

时间复杂度为O(nlogn)

posted @   Nastia  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示