题面

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

二分答案,然后我们要把一圈分成三块,使这三块的大小都$\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. 如何通过Xcode 5中集成的XCTest框架进行简单的单元测试

    XCTest 1.第一个单元测试 XCTest是Xcode 5中自带的测试框架 下面从一个Demo开始.首先用Xcode新建一个工程UnitTestDemo,工程目录结构如下: 可以看到工程下面多了一 ...

  2. WPF使用附加属性绑定,解决data grid列绑定不上的问题

    背景 需要对datagrid的列header添加自定义属性,然后绑定,并根据不同的列header绑定不同的值,传统的加扩展类太麻烦,而附加属性的特点更适用于这种场景. 1.xaml 代码 <Da ...

  3. 相机 感光度iso,焦距,光圈,ccd 和 噪点, 景深关系表格

    表格 矩阵 感官度iso: 越低曝光速度越慢,所谓慢工出细活,成像质量会好,如果形成的话. 但是因为慢,所以要更多的光量,才能画完. 就需要更慢的快门 (但是太慢手抖的话就糊掉,或者动的物体形成轨迹. ...

  4. NSLayoutConstraint.constraintsWithVisualFormat详解,以及AlignAllCenterY

    NSLayoutConstraint.constraintsWithVisualFormat详解,以及AlignAllCenterY 转载2015-07-08 18:02:02 鉴于苹果官方文档的解释 ...

  5. 组件开发中的Controller View模式

    “Controller View”模式: 组件嵌套中,最顶层的组件只管理State 子组件为纯组件 顶层组件分配State给子组件,作为子组件的props 子组件接受顶层组件发来的State作为自身的 ...

  6. Django模型中字段属性choice的使用

    根据Django官方文档: from django.db import models class Student(models.Model): FRESHMAN = 'FR' SOPHOMORE = ...

  7. 【OS_Linux】Linux 基本命令整理

    1. 查看目录文件:ls2. 打印当前工作目录:pwd3. 查看文件内容:cat 文件名4. 打开编辑器:vim 文件名 1 2 3 4 5 修改:按Insert键 退出修改模式:按Esc 键 进入输 ...

  8. java代码生成二维码

    java代码生成二维码一般步骤 常用的是Google的Zxing来生成二维码,生成的一般步骤如下: 一.下载zxing-core的jar包: 二.需要创建一个MatrixToImageWriter类, ...

  9. modelsim安装调试

    modelsim,debug:“unable to checkout a viewer license necessary for use of the modelsim graphical user ...

  10. python--内置函数03

    一 . 正则表达式 匹配字符串 元字符 . 除了换行 \w 数字, 字母, 下划线 \d 数字 \s 空白符 \n \t \b 单词的边界 \W 非xxx \D \S [ ] 字符组 or的关系 [^ ...