题面

一看到求“最小值的最大值”这种问题,就能想到二分了。

二分答案,然后我们要把一圈分成三块,使这三块的大小都$\geq mid$。做法是把环展开成2倍长度的链,先钦定一个起点,然后根据前缀和再二分一下前两块的最小大小(注意前两块要连着),第三块用一圈的大小减去前两块的大小即可得到。如果第三块的大小$\geq mid$就返回$true$,提高答案范围;否则返回$false$,降低答案范围。

这样就能卡着最优情况下最小那一块的最大值从而得出答案了。

上面这种做法是$O(n*log_n*log_a)$,且二分次数多,常数较大,比较卡时。能不能不二分前两块的最小大小而快速求出?

如果做过“不超过某数的最大区间和(所有数非负)”这种单调性显然的题的话应该知道,钦定起点、确定大小这样一个做法在单调意义下可以滑动窗口。在这里前两块其实也是滑窗,因此省掉了内层的二分。时间复杂度$O(n*log_a)$。

当然,把枚举起点的循环放到二分外边会快一点。

也可以改变枚举量(WZQ的做法),就是把二分最小大小 改为 二分前两块的长度,提高答案范围当且仅当第一块的大小$\leq mid$,第二、三块的大小$\geq mid$。这样时间复杂度大概为$O(n*log_n*log_n)$。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 100002
inline int read(){
int x=; bool f=; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=;
for(; isdigit(c);c=getchar()) x=(x<<)+(x<<)+(c^'');
if(f) return x;
return -x;
}
int n,n1;
long long a[N<<],sfx[N<<];
long long judge(long long x){
//printf("x:%d\n",x);
int dir,dir2; long long mx=-;
for(int i=;sfx[i+n1-]-sfx[i-]>=x*;++i){
dir=lower_bound(sfx+i,sfx+i+n1,x+sfx[i-])-sfx;
if(sfx[dir]-sfx[i-]>x) --dir;
if(dir<i) continue;
dir2=lower_bound(sfx+dir+,sfx+i+n1,x+sfx[dir])-sfx;
if(dir2<=dir) dir2=dir+;
//printf("%d %d %lld %lld %lld\n",dir,dir2,sfx[dir]-sfx[i-1],sfx[dir2]-sfx[dir],sfx[i+n1-1]-sfx[dir2]);
//cout<<(dir2<i+n1-1)<<' '<<(sfx[i+n1-1]-sfx[dir2]>=sfx[dir]-sfx[i-1])<<'\n';
if(dir2<i+n1- && sfx[i+n1-]-sfx[dir2]>=sfx[dir]-sfx[i-]) mx=max(mx,sfx[dir]-sfx[i-]);
}
//printf("MX:%lld\n",mx);
return mx;
} int main(){
n=n1=read();
int i;
for(i=;i<=n;i++) a[i]=a[i+n]=read(), sfx[i]=sfx[i-]+a[i];
n<<=;
for(;i<=n;i++) sfx[i]=sfx[i-]+a[i];
long long l=,r=(sfx[n]+n-)/,mid,ret,ans=-;
while(l<=r){
mid=(l+r)>>;
ret=judge(mid);
if(ret!=-) ans=ret, l=mid+;
else r=mid-;
}
printf("%lld\n",ans);
return ;
}

最外层二分答案(较慢)

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 100002
inline int read(){
int x=; bool f=; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=;
for(; isdigit(c);c=getchar()) x=(x<<)+(x<<)+(c^'');
if(f) return x;
return -x;
}
int n,n1;
long long a[N<<],sfx[N<<]; long long judge(int i,long long x){
//printf("faq:%d %lld\n",i,x);
int dir,dir2;
dir=lower_bound(sfx+i,sfx+i+n1,x+sfx[i-])-sfx;
if(sfx[dir]-sfx[i-]>x) --dir;
if(dir<i || dir>=i+n1-) return -; dir2=lower_bound(sfx+dir+,sfx+i+n1,(sfx[dir]<<)-sfx[i-])-sfx;
if(dir2>=i+n1-) return -; //printf("%d %d %lld %lld %lld\n",dir,dir2,sfx[dir]-sfx[i-1],sfx[dir2]-sfx[dir],sfx[i+n1-1]-sfx[dir2]);
if(sfx[i+n1-]-sfx[dir2]>=sfx[dir]-sfx[i-]) return sfx[dir]-sfx[i-];
return -;
}
int main(){
n=n1=read();
int i;
for(i=;i<=n;i++) a[i]=a[i+n]=read(), sfx[i]=sfx[i-]+a[i];
n<<=;
for(;i<=n;i++) sfx[i]=sfx[i-]+a[i];
int dir,dir2;
long long ans=-;
for(int i=; i<=n1; i++){
long long l=,r=sfx[n1]/,mid,ret,res=-;
while(l<=r){
mid=(l+r)>>;
ret=judge(i,mid);
if(ret!=-) res=ret, l=mid+;
else r=mid-;
}
ans=max(ans,res);
}
printf("%lld\n",ans);
return ;
}

最外层枚举起点(快一点)

 #include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define ll long long
using namespace std;
const int maxn=+;
inline int read(){
int x=,f=;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=(x<<)+(x<<)+ch-'';
return x*f;
}
ll n,a[maxn],sum,num[maxn]; bool erfe(ll l,ll r,ll he){
ll l1=l,r1=r,ans=;
while(r1>=l1){
ll mid=r1+l1>>;
ll qq=num[mid]-num[l-],ww=num[n]-qq-he;
if(qq>=he){
if(ww>=he)return ;
else r1=mid-;
}
else l1=mid+;
}
return ;
}
ll aa;
ll erf(ll l,ll r){
ll l1=l,r1=r,ans=;
while(r1>=l1){
ll mid=r1+l1>>;
if(num[mid]-num[l-]<=sum){
if(erfe(mid+,r,num[mid]-num[l-]))ans=max(ans,num[mid]-num[l-]),l1=mid+;
else r1=mid-;
}
else r1=mid-;
}
return ans;
} ll ans=;
void zj(){
for(ll i=;i<=n;i++){
ans=max(ans,erf(i,n+i-));
}
printf("%lld",ans);
return ;
} int main(){
n=read();
for(ll i=;i<=n;i++){
a[i]=read();
num[i]=num[i-]+a[i];
sum+=a[i];
}
for(ll i=n+;i<=*n;i++)a[i]=a[i-n],num[i]=num[i-]+a[i];
sum=sum/;
zj();
return ;
}

WZQ的做法

滑窗没写先凑乎吧。

【2018.10.1】「JOI 2014 Final」年轮蛋糕的更多相关文章

  1. 【题解】LOJ2759. 「JOI 2014 Final」飞天鼠(最短路)

    [题解]LOJ2759. 「JOI 2014 Final」飞天鼠(最短路) 考虑最终答案的构成,一定是由很多飞行+一些上升+一些下降构成. 由于在任何一个点上升或者下降代价是一样的,所以: 对于上升操 ...

  2. 「JOI 2014 Final」飞天鼠

    「JOI 2014 Final」飞天鼠 显然向上爬是没有必要的,除非会下降到地面以下,才提高到刚好为0. 到达一个点有两种情况:到达高度为0和不为0. 对于高度不为0的情况,显然花费的时间越少高度越高 ...

  3. loj 2759「JOI 2014 Final」飞天鼠

    loj 这题有在一棵树上上升或者下降的操作,稍加分析后可以发现上升操作如果不是一定要做(指高度不足以到下一棵树或者是最后到达\(n\))就不做,下降操作也是如果不是一定要做(指到达下一棵树时高度过高) ...

  4. 「JOI 2014 Final」裁剪线

    做法一 首先将边界也视作四条裁剪线,整个平面作为一张纸,视存在 \(y = -\infty, y = +\infty, x = -\infty, x = +\infty\) 四条直线. 按照纵坐标依次 ...

  5. 「JOI 2017 Final」JOIOI 王国

    「JOI 2017 Final」JOIOI 王国 题目描述 题目译自 JOI 2017 Final T3「 JOIOI 王国 / The Kingdom of JOIOI」 JOIOI 王国是一个 H ...

  6. 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)

    LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...

  7. 「JOI 2015 Final」分蛋糕 2

    「JOI 2015 Final」分蛋糕 2 题解 这道题让我想起了新年趣事之红包这道DP题,这道题和那道题推出来之后的做法是一样的. 我们可以定义dp[i][len][1] 表示从第i块逆时针数len ...

  8. 「JOI 2015 Final」城墙

    「JOI 2015 Final」城墙 复杂度默认\(m=n\) 暴力 对于点\((i,j)\),记录\(ld[i][j]=min(向下延伸的长度,向右延伸的长度)\),\(rd[i][j]=min(向 ...

  9. 「JOI 2015 Final」舞会

    「JOI 2015 Final」舞会 略微思考一下即可知该过程可以化为一棵树.(3个贵族中选择1个,即新建一个节点连向这3个贵族). 该树的结点个数为\(2n\). 考虑二分答案mid. 判定的是公主 ...

随机推荐

  1. (1)Ngixn 编译安装 (版本:1.12.1)

        1.创建用户和群组     groupadd nginx     创建一个用户,不允许登陆和不创主目录     useradd -s /sbin/nologin -g nginx -M ngi ...

  2. HTTPs与HTTP的性能

    (参考:https://blog.csdn.net/chinafire525/article/details/78911734 https://blog.csdn.net/hherima/articl ...

  3. Swift REPL入门介绍

    Xcode 6.1 引入了一个新特性用来辅助Swift开发,即Read Eval Print Loop(“读取-求值-输出”循环,简称REPL).熟悉解释型语言的开发者将会对这个命令行环境感到舒适,而 ...

  4. Vue项目经验

    Vue项目经验 setInterval路由跳转继续运行并没有及时进行销毁比如一些弹幕,走马灯文字,这类需要定时调用的,路由跳转之后,因为组件已经销毁了,但是setInterval还没有销毁,还在继续后 ...

  5. Fortran学习笔记5(数组Array)

    数组的声明方式 一维数组 二维数组 多维数组 数组索引值的改变 自定义类型的数组定义 对数组内容的设置 利用隐含式循环设置数组初值 对整个数组操作 对部分数组的操作 where函数 Forall函数 ...

  6. 数据库事务ACID和事务的隔离级别

    借鉴:https://blog.csdn.net/zh521zh/article/details/69400053和https://blog.csdn.net/May_3/article/detail ...

  7. Bzoj 1083: [SCOI2005]繁忙的都市 (最小生成树)

    Bzoj 1083: [SCOI2005]繁忙的都市 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1083 此题是最小瓶颈生成树的裸题. ...

  8. (34)zabbix Queue队列

    概述 queue(队列)显示监控项等待刷新的时间,可以看到每种agent类型刷新时间,通过queue可以更好的体现出监控的一个指标.正常情况下,是一片绿色. 如果出现过多红色,那么需要留意一下.我们也 ...

  9. ubuntu 安装 php7.2

    sudo apt-get install software-properties-common python-software-properties sudo add-apt-repository p ...

  10. Python操作12306抢票脚本

    有一段时间没有使用Python了,前几天经朋友提起一篇关于用Python实现抢火车票的文章,百度了实现抢火车票的技术细节,网上却有不少资料,也不是新鲜的东西.在了解了一些技术手段,阅读了一些大神的博文 ...