【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. 判定的是公主 ...
随机推荐
- C# 操作字符串,在某些特定的字符后面或前面添加其它字符
C# 操作字符串,在某些特定的字符后面或前面添加其它字符,解决方法: 字符串替换或正则表达式替换即可. 示例:实现的是在每个“第”前面添加一个逗号,在每个“方案”后面添加一个冒号. string s ...
- write命令
write——给用户发信息,以Ctrl+D保存结束 命令所在路径:/usr/bin/write 示例1: # write xiaohua 执行命令后可以输入需要发送的信息,如下: 同时xiaohua收 ...
- 【转载】K-mer算法
k-mer是指将reads分成包含k个碱基的字符串,一般长短为m的reads可以分成m-k+1个k-mers.举个例子吧,为了简化,有这么个reads(当然实际比这个长):AACTGACTGA.如果k ...
- ios之UIActionSheet
UIActionSheet是在IOS弹出的选择按钮项,可以添加多项,并为每项添加点击事件. 为了快速完成这例子,我们打开Xcode 4.3.2, 先建立一个single view applicatio ...
- ZJOI2018游记Round2
Day0 趁着空档还溜回班上了一节物理课:瓢泼之中在9:00赶往余姚,车程3h+-- 中饭在一家饭馆,味道海星. 晚上和ykh,chj,xzt溜去吃一鸣和烧烤.一鸣不错,烧烤的话我因为口腔溃疡没怎么吃 ...
- 《Spring源码深度解析》第二章 容器的基本实现
入门级别的spring配置文件 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi=&q ...
- asyn_fifo
//Module Name:afifo_ctrl //Description:parameterized afifo module afifo_ctrl( clk_push, rst_push_n, ...
- redis 散列学习要点记录
散列类型键值也是种字典结构,存储了字段和字段值的映射,字段值只能是字符串,不可以是其他类型(redis数据类型都不可嵌套使用其他类型),散列类型键可以有2的32次方减1个字段 散列的命令组 hset ...
- 【php】运算符优先级界定
<?php $i = 1; $array[$i] = $i++; print_r($array);die; //输出 Array([2] => 1) $a = 1; echo $a + $ ...
- 力扣题目汇总(反转字符串中的单词,EXCEL表列序号,旋置矩阵)
反转字符串中的单词 III 1.题目描述 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序. 示例 1: 输入: "Let's take LeetCode ...