【2018.10.1】「JOI 2014 Final」年轮蛋糕
题面
一看到求“最小值的最大值”这种问题,就能想到二分了。
二分答案,然后我们要把一圈分成三块,使这三块的大小都$\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」年轮蛋糕的更多相关文章
- 【题解】LOJ2759. 「JOI 2014 Final」飞天鼠(最短路)
[题解]LOJ2759. 「JOI 2014 Final」飞天鼠(最短路) 考虑最终答案的构成,一定是由很多飞行+一些上升+一些下降构成. 由于在任何一个点上升或者下降代价是一样的,所以: 对于上升操 ...
- 「JOI 2014 Final」飞天鼠
「JOI 2014 Final」飞天鼠 显然向上爬是没有必要的,除非会下降到地面以下,才提高到刚好为0. 到达一个点有两种情况:到达高度为0和不为0. 对于高度不为0的情况,显然花费的时间越少高度越高 ...
- loj 2759「JOI 2014 Final」飞天鼠
loj 这题有在一棵树上上升或者下降的操作,稍加分析后可以发现上升操作如果不是一定要做(指高度不足以到下一棵树或者是最后到达\(n\))就不做,下降操作也是如果不是一定要做(指到达下一棵树时高度过高) ...
- 「JOI 2014 Final」裁剪线
做法一 首先将边界也视作四条裁剪线,整个平面作为一张纸,视存在 \(y = -\infty, y = +\infty, x = -\infty, x = +\infty\) 四条直线. 按照纵坐标依次 ...
- 「JOI 2017 Final」JOIOI 王国
「JOI 2017 Final」JOIOI 王国 题目描述 题目译自 JOI 2017 Final T3「 JOIOI 王国 / The Kingdom of JOIOI」 JOIOI 王国是一个 H ...
- 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)
LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...
- 「JOI 2015 Final」分蛋糕 2
「JOI 2015 Final」分蛋糕 2 题解 这道题让我想起了新年趣事之红包这道DP题,这道题和那道题推出来之后的做法是一样的. 我们可以定义dp[i][len][1] 表示从第i块逆时针数len ...
- 「JOI 2015 Final」城墙
「JOI 2015 Final」城墙 复杂度默认\(m=n\) 暴力 对于点\((i,j)\),记录\(ld[i][j]=min(向下延伸的长度,向右延伸的长度)\),\(rd[i][j]=min(向 ...
- 「JOI 2015 Final」舞会
「JOI 2015 Final」舞会 略微思考一下即可知该过程可以化为一棵树.(3个贵族中选择1个,即新建一个节点连向这3个贵族). 该树的结点个数为\(2n\). 考虑二分答案mid. 判定的是公主 ...
随机推荐
- nGrinder技术架构图
- .Net Mvc 返回Json,动态生成EasyUI Tree
最近做一个项目,开始接触EasyUI,感觉很强大,很适合我这种对前台不是很感冒的人.在学习Tree的过程中,感觉网上的资料挺乱的,很多只是把EasyUI API 抄了一遍.现在把最近这段时间的学到的, ...
- win7 ghost 纯净版最新系统下载
这个系统是WIN7系统GHOST版装机旗舰版 SP1,更新了系统补丁到2016-02(可通过微软漏洞扫描和卫士漏洞扫描),升级Internet Explorer为IE9,增加数款驱动的支持,支持最新的 ...
- Mac app 破解之路
6年之前一直做过一些内存挂,脚本挂.都是比较低级的技术. 这几年期间,断断续续利用业余时间学了一些汇编的知识,当时只是想着破解游戏. 所有的黑技术都是业余自学的,没有老师可以问,只能百度和自己领悟,比 ...
- 学习C语言库函数
使用C语言功能强大的函数,我们需要包含头文件 #include<math.h>. 1)取两个数的较大值或较小值函数: double a = 9.9; double b = 6.6; pri ...
- sha1、base64、ase加密
<!DOCTYPE html><html><head><title>sha1.base64.ase加密</title><meta ch ...
- (19)zabbix Applications使用介绍
介绍 Applications(我们翻译为应用程序)是item的一个组. 例如我们要监控MySQL,我们可以将所有和MySQL相关的item放到这个应用程序中. 例如MySQL的availabilit ...
- Python面向对象(约束,异常处理,md5加密)(五)
1. 类的约束 1. 写一个父类. 父类中的某个方法要抛出一个异常 NotImplementedError class Base: def login(self): raise NotImplemen ...
- windowsServer2008搭建域服务器
为什么要搭建域? 工作组的分散管理模式不适合大型的网络环境下工作,域模式就是针对大型的网络管理需求设计的,就是共享用户账号,计算机账号和安全策略的计算机集合.域中集中存储用户账号的计算机就是域控器,域 ...
- Python9-继承1-day24(大年初一)
#面向对象编程:'''思想:角色的抽象,创建类,创建角色,面对对象的关键字class 类名: 静态属性 = ‘aaa' def __init__(self):pass 类名.静态属性 ———存储在类的 ...