题意:在 Ninian 的花园里,有许多琼花,环绕着中间的凉亭。有 N 片琼花,组成一个环。Ninian 想在凉亭中发动 [セチの祈り] , 需要划分出三个区域的琼花,为了平均,要最大化面积最小的区域的面积。划分区域:即用三刀把这个环分成三段,每段称之为一个区域。
链接:点我
最大化最小,显然是二分,在判断答案的过程中用贪心
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 typedef long long ll; 13 #define cl(a) memset(a,0,sizeof(a)) 14 #define ts printf("***** "); 15 const int MAXN=200100; 16 int n,m,tt; 17 ll sum[MAXN],a[MAXN]; 18 bool check(ll x) 19 { 20 int mid=0,last=0; 21 for(int i=0;i<n;i++) //枚举起点,这里用的是贪心策略,每次尽量选大一点的面积 22 { 23 while(i+n>=mid&&sum[mid]-sum[i]<x) mid++; 24 while(i+n>=last&&sum[last]-sum[mid]<x) last++; 25 if(sum[i+n]-sum[last]>=x) return true; 26 } 27 return false; 28 } 29 int main() 30 { 31 int i,j,k; 32 /*#ifndef ONLINE_JUDGE 33 freopen("1.in","r",stdin); 34 #endif*/ 35 while(~scanf("%d",&n)) 36 { 37 cl(sum); 38 for(i=1;i<=n;i++) 39 { 40 scanf("%lld",a+i); 41 sum[i]=sum[i-1]+a[i]; 42 } 43 for(i=1;i<=n;i++) 44 { 45 sum[i+n]=sum[i+n-1]+a[i]; 46 } 47 ll l=0,r=100000000000000,ans=0; 48 49 while(l<=r) 50 { 51 ll mid=(l+r)>>1; 52 if(check(mid)) 53 { 54 ans=mid; 55 l=mid+1; 56 } 57 else r=mid-1; 58 } 59 printf("%lld ",ans); 60 } 61 }