题目传送门
这道题看似复杂,其实我们可以二分答案再check,二分的是最少的礼物,check的是是否可行,显然如果输入的n是偶数的话,那么我们交错地放礼物,也就是说答案就是max(r[i]+r[i+1]),如果是奇数的话,那么我们除了第一个人放1到r[1]号礼物,其他的人如果是编号偶数的话就尽量往前放,如果是编号奇数的话就尽量往后放,那么我们维护一个left和一个right数组,分别存第几个人在区间1到r[1]和区间r[1]+1到p放了几个物体,由于是圆桌,所以最后判定第n个人的左边有没有放礼物就可以了,因为第n个人和第1个人是坐在一起的,而第一个人有第1到r[1]号的礼物,因此如果第n个人也有1-r[1]这些礼物中的一些,两个人就会生气
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN=100000+10;
int n,r[MAXN],Right[MAXN],Left[MAXN];
bool check(int p){
int x=r[1],y=p-r[1];
Left[1]=x;Right[1]=0;
for(register int i=2;i<=n;i++){
if(i%2==1){
Right[i]=min(y-Right[i-1],r[i]);
Left[i]=r[i]-Right[i];
}else{
Left[i]=min(x-Left[i-1],r[i]);
Right[i]=r[i]-Left[i];
}
}
return Left[n]==0;
}
int main(){
while(scanf("%d",&n)!=EOF&&n){
for(register int i=1;i<=n;i++)scanf("%d",&r[i]);
if(n==1){printf("%d\n",r[1]);continue;}
r[n+1]=r[1];
int L=0,R=0;
for(register int i=1;i<=n;i++) L=max(r[i]+r[i+1],L);
if(n%2==1){
for(register int i=1;i<=n;i++) R=max(R,r[i]*3);
while(L<R){
int mid=L+((R-L)>>1);
if(check(mid)) R=mid;
else L=mid+1;
}
}
printf("%d\n",L);
}
return 0;
}