Uva 长城守卫——1335 - Beijing Guards
二分查找+一定的技巧
1 #include<iostream> 2 using namespace std; 3 4 const int maxn=100000+10; 5 int n,r[maxn],Left[maxn],Right[maxn];//因为不用计算方案,所以可以按【1~r[i]】和【r[i]+1~p】中各拿几个分,当时没想到这个用set类写了个超耗时间的~~~~(>_<)~~~~ 6 7 bool ok(int p) 8 { 9 int x=r[1],y=p-r[1]; 10 Left[1]=x;Right[1]=0; 11 for(int i=2;i<=n;i++) 12 { 13 if(i&1) 14 { 15 Right[i]=min(y-Right[i-1],r[i]);//奇数守卫先拿右边 16 Left[i]=r[i]-Right[i];//再看左边要几个 17 } 18 else 19 { 20 Left[i]=min(x-Left[i-1],r[i]);//偶数守卫先拿左边 21 Right[i]=r[i]-Left[i];//再看右边要几个 22 } 23 } 24 return Left[n]==0;//第n个守卫左边为0时 25 } 26 27 int main() 28 { 29 while(cin>>n&&n) 30 { 31 for(int i=1;i<=n;i++) 32 cin>>r[i]; 33 if(n==1) {cout<<r[1]<<endl;continue;}//这个地方坑了我 34 r[n+1]=r[1]; 35 int L=0,R=0; 36 for(int i=1;i<=n;i++) L=max(L,r[i]+r[i+1]); 37 if(n&1) 38 { 39 for(int i=1;i<=n;i++) R=max(R,r[i]*3); 40 while(L<R) 41 { 42 int M=(L+R)/2; 43 if(ok(M)) R=M; 44 else L=M+1; 45 } 46 } 47 cout<<L<<endl; 48 } 49 }