题面

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

二分答案,然后我们要把一圈分成三块,使这三块的大小都$\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. Bootstrap 入门到精通

    介绍 Bootstrap,来自 Twitter,是目前最受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷.Bootstr ...

  2. Web项目之Django实战问题剖析

    基于AdminLTE-master模板的后台管理系统 左侧菜单栏的二级标签设计 面包屑 Django文件上传 后台管理系统CRM项目设计流程分析

  3. vue 实现走马灯效果

    Part.1  问题 在写一个H5页面时遇到一个需求,头部公告需要滚动变换,需要实现一个走马灯效果 Part.2  实现 我的做法:利用 定时器 + CSS3 变换公告数组的顺序 从而实现走马灯效果 ...

  4. Mysql,SqlServer,Oracle主键自动增长的设置

    在mysql中,如果把表的主键设为auto_increment类型,数据库就会自动为主键赋值.例如: CREATE TABLE google(id INT AUTO_INCREMENT PRIMARY ...

  5. 精选30道Java笔试题附答案分析

    精选30道Java笔试题解答 都是一些非常非常基础的题,是我最近参加各大IT公司笔试后靠记忆记下来的,经过整理献给与我一样参加各大IT校园招聘的同学们,纯考Java基础功底,老手们就不用进来了,免得笑 ...

  6. 牛客网NOIP赛前集训营-普及组(第二场)和 牛客网NOIP赛前集训营-提高组(第二场)解题报告

    目录 牛客网NOIP赛前集训营-普及组(第二场) A 你好诶加币 B 最后一次 C 选择颜色 D 合法括号序列 牛客网NOIP赛前集训营-提高组(第二场) A 方差 B 分糖果 C 集合划分 牛客网N ...

  7. 【贪心 堆】luoguP2672 推销员

    堆维护,贪心做法 题目描述 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户.螺丝街一共有N家住户,第i家住户到入口的距离为S ...

  8. 【OS_Linux】yum命令安装软件

    1.YUM的简介 Yum(全称为 Yellow dog Updater, Modified)是一个rpm包管理器.它能够从指定的服务器上自动下载RPM包并安装,可以自动处理包之间的依赖性关系,并且一次 ...

  9. grub加密。

    一.介绍 安全无小事  linux系统的安全分为很多方面,什么端口啊,什么网络啊,听着都特么烦,今天谈谈最简单明显的密码安全. 二.单用户模式 单用户模式个人觉得相当有用,可以用来修复系统,修改密码… ...

  10. Shell中各种括号的作用

    一.小括号,圆括号() 1.单小括号 () ① 命令组.括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用.括号中多个命令之间用分号隔开,最后一个命令可以没有分号 ...