【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)$。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define N 100002 8 inline int read(){ 9 int x=0; bool f=1; char c=getchar(); 10 for(;!isdigit(c);c=getchar()) if(c=='-') f=0; 11 for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0'); 12 if(f) return x; 13 return 0-x; 14 } 15 int n,n1; 16 long long a[N<<1],sfx[N<<1]; 17 long long judge(long long x){ 18 //printf("x:%d\n",x); 19 int dir,dir2; long long mx=-1; 20 for(int i=1;sfx[i+n1-1]-sfx[i-1]>=x*3;++i){ 21 dir=lower_bound(sfx+i,sfx+i+n1,x+sfx[i-1])-sfx; 22 if(sfx[dir]-sfx[i-1]>x) --dir; 23 if(dir<i) continue; 24 dir2=lower_bound(sfx+dir+1,sfx+i+n1,x+sfx[dir])-sfx; 25 if(dir2<=dir) dir2=dir+1; 26 //printf("%d %d %lld %lld %lld\n",dir,dir2,sfx[dir]-sfx[i-1],sfx[dir2]-sfx[dir],sfx[i+n1-1]-sfx[dir2]); 27 //cout<<(dir2<i+n1-1)<<' '<<(sfx[i+n1-1]-sfx[dir2]>=sfx[dir]-sfx[i-1])<<'\n'; 28 if(dir2<i+n1-1 && sfx[i+n1-1]-sfx[dir2]>=sfx[dir]-sfx[i-1]) mx=max(mx,sfx[dir]-sfx[i-1]); 29 } 30 //printf("MX:%lld\n",mx); 31 return mx; 32 } 33 34 int main(){ 35 n=n1=read(); 36 int i; 37 for(i=1;i<=n;i++) a[i]=a[i+n]=read(), sfx[i]=sfx[i-1]+a[i]; 38 n<<=1; 39 for(;i<=n;i++) sfx[i]=sfx[i-1]+a[i]; 40 long long l=0,r=(sfx[n]+n-1)/3,mid,ret,ans=-1; 41 while(l<=r){ 42 mid=(l+r)>>1; 43 ret=judge(mid); 44 if(ret!=-1) ans=ret, l=mid+1; 45 else r=mid-1; 46 } 47 printf("%lld\n",ans); 48 return 0; 49 }
最外层二分答案(较慢)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define N 100002 8 inline int read(){ 9 int x=0; bool f=1; char c=getchar(); 10 for(;!isdigit(c);c=getchar()) if(c=='-') f=0; 11 for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0'); 12 if(f) return x; 13 return 0-x; 14 } 15 int n,n1; 16 long long a[N<<1],sfx[N<<1]; 17 18 long long judge(int i,long long x){ 19 //printf("faq:%d %lld\n",i,x); 20 int dir,dir2; 21 dir=lower_bound(sfx+i,sfx+i+n1,x+sfx[i-1])-sfx; 22 if(sfx[dir]-sfx[i-1]>x) --dir; 23 if(dir<i || dir>=i+n1-2) return -1; 24 25 dir2=lower_bound(sfx+dir+1,sfx+i+n1,(sfx[dir]<<1)-sfx[i-1])-sfx; 26 if(dir2>=i+n1-1) return -1; 27 28 //printf("%d %d %lld %lld %lld\n",dir,dir2,sfx[dir]-sfx[i-1],sfx[dir2]-sfx[dir],sfx[i+n1-1]-sfx[dir2]); 29 if(sfx[i+n1-1]-sfx[dir2]>=sfx[dir]-sfx[i-1]) return sfx[dir]-sfx[i-1]; 30 return -1; 31 } 32 int main(){ 33 n=n1=read(); 34 int i; 35 for(i=1;i<=n;i++) a[i]=a[i+n]=read(), sfx[i]=sfx[i-1]+a[i]; 36 n<<=1; 37 for(;i<=n;i++) sfx[i]=sfx[i-1]+a[i]; 38 int dir,dir2; 39 long long ans=-1; 40 for(int i=1; i<=n1; i++){ 41 long long l=1,r=sfx[n1]/3,mid,ret,res=-1; 42 while(l<=r){ 43 mid=(l+r)>>1; 44 ret=judge(i,mid); 45 if(ret!=-1) res=ret, l=mid+1; 46 else r=mid-1; 47 } 48 ans=max(ans,res); 49 } 50 printf("%lld\n",ans); 51 return 0; 52 }
最外层枚举起点(快一点)
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<queue> 8 #define ll long long 9 using namespace std; 10 const int maxn=1000000+101010; 11 inline int read(){ 12 int x=0,f=1;char ch=getchar(); 13 for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 14 for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-'0'; 15 return x*f; 16 } 17 ll n,a[maxn],sum,num[maxn]; 18 19 20 bool erfe(ll l,ll r,ll he){ 21 ll l1=l,r1=r,ans=0; 22 while(r1>=l1){ 23 ll mid=r1+l1>>1; 24 ll qq=num[mid]-num[l-1],ww=num[n]-qq-he; 25 if(qq>=he){ 26 if(ww>=he)return 1; 27 else r1=mid-1; 28 } 29 else l1=mid+1; 30 } 31 return 0; 32 } 33 ll aa; 34 ll erf(ll l,ll r){ 35 ll l1=l,r1=r,ans=0; 36 while(r1>=l1){ 37 ll mid=r1+l1>>1; 38 if(num[mid]-num[l-1]<=sum){ 39 if(erfe(mid+1,r,num[mid]-num[l-1]))ans=max(ans,num[mid]-num[l-1]),l1=mid+1; 40 else r1=mid-1; 41 } 42 else r1=mid-1; 43 } 44 return ans; 45 } 46 47 ll ans=0; 48 void zj(){ 49 for(ll i=1;i<=n;i++){ 50 ans=max(ans,erf(i,n+i-1)); 51 } 52 printf("%lld",ans); 53 return ; 54 } 55 56 int main(){ 57 n=read(); 58 for(ll i=1;i<=n;i++){ 59 a[i]=read(); 60 num[i]=num[i-1]+a[i]; 61 sum+=a[i]; 62 } 63 for(ll i=n+1;i<=2*n;i++)a[i]=a[i-n],num[i]=num[i-1]+a[i]; 64 sum=sum/3; 65 zj(); 66 return 0; 67 }
WZQ的做法
滑窗没写先凑乎吧。
转载于:https://www.cnblogs.com/scx2015noip-as-php/p/9734669.html
【2018.10.1】「JOI 2014 Final」年轮蛋糕相关推荐
- 「JOI 2016 Final」断层
嘟嘟嘟 今天我们模拟考这题,出的是T3.实在是没想出来,就搞了个20分暴力(还WA了几发). 这题关键在于逆向思维,就是考虑最后的\(n\)的个点刚开始在哪儿,这样就减少了很多需要维护的东西. 这就让 ...
- Luogu P5103 「JOI 2016 Final」断层 树状数组or线段树+脑子
太神仙了这题... 原来的地面上升,可以倒着操作(时光倒流),转化为地面沉降,最后的答案就是每个点的深度. 下面的1,2操作均定义为向下沉降(与原题意的变换相反): 首先这个题目只会操作前缀和后缀,并 ...
- T3:LOJ2332「JOI 2017 Final」焚风现象.cpp
记录差值 然后每次运算一下头和尾 如果尾端是最后一次增加则不用运算尾端 详见代码 #include<iostream> #include<cstdio> #include< ...
- Libre OJ P2332「JOI 2017 Final」焚风现象【差分思想】By cellur925
题目传送门 这道题开始看起来会很晕...\(qwq\).首先我们要明确题目中的海拔&&温度.温度是受海拔影响的,每次改变的是海拔,我们求的是温度. 我们开始读入的时候便可以处理出开始\ ...
- 【题解】LOJ3254:「JOI 2020 Final」集邮比赛 3
原题传送门 发现 n < = 200 n<=200 n<=200,那么我们就可以想一个 O ( n 3 ) O(n^3) O(n3)的dp 发现每次肯定是向左/右推进 可以令 d p ...
- 「JOISC 2014 Day3」稻草人
「JOISC 2014 Day3」稻草人 问题简述 解析 代码 问题简述 链接 https://loj.ac/problem/2880 给定 n n n个稻草人(横纵坐标是不大于 1 0 9 10 ...
- 「JOISC 2014 Day1」巴士走读
「JOISC 2014 Day1」巴士走读 题解部分: (如果不怎么喜欢看推导的人可以直接看下面的关键部分,在段尾会有标注(或者看完定义直接看代码)) 本题让我们求到达点n需要最晚何时到达点1,我们可 ...
- 「JOISC 2014 Day4」挂饰(背包DP)题解
题目翻译 JOI 君有 n n n 个装在手机上的挂饰,编号为 1 - n 1 \ldots n 1-n. JOI 君可以将其中一些挂饰装在手机上. JOI 君的挂饰有一些与众不同--其中的一些挂饰附 ...
- [JOI 2014 Final]裁剪线
题目 传送门 to LOJ 思路 思路来自于官方题解,有兴趣的 日语高超的 可以自己找来看一看.这里就直接贴出翻译后的截图了 考虑一种并查集的做法,给每一个"区域"分配一个并查集编 ...
最新文章
- 【drp 12】再识转发和重定向:SpringMVC无法跳转页面
- C# 2.0 套接字编程实例初探
- Java实现Google第三方登录
- Maven学习-优化和重构POM
- 高效KMP字符匹配算法就这么简单
- P8U8 IT这块出书门槛相对比较低
- Kotlin学习笔记18 反射Part2
- java与sql心得体会_学习心得
- 2019最新k8s集群搭建教程 (centos k8s 搭建)
- 【安全狐】robots协议详解(robots.txt)
- jQuery 倒计时插件
- APK无法识别gsensor问题剖析
- 郑州轻工业大学oj平台 c语言 1008 美元和人民币的换算
- python分离arw与jpg图片
- Linux终端Terminal常用快捷键
- PHP开发环境配置指南
- 谁要GMAIL和Orkut的邀请?
- 出现这个错误的解决方法No enclosing instance of type 类名 is accessible. Must qualify the allocation with
- [转]为ERP的定义“拨乱反正”
- 准备搬家,送所有书籍!
热门文章
- 做一个简单的“远程”开关 ESP8266 + APP
- winform制作音乐播放器
- 不同直径的圆转一圈后,滚过的距离相同?谈一下亚里士多德车轮悖论与无穷小
- TIME_WAIT状态存在的意义
- 使用计算机需要准备硬件和什么,当个人计算机需要使用ADSL访问Internet时,所需的基本硬件设施是什么?...
- Springboot项目 logging level配置
- FPGA与CPLD之区别
- 两种电子配线架的原理比较
- Android之实现手机号码拦截
- [HITCON 2016]Leaking-nodejsVM沙箱逃逸