描述
在 Ninian 的花园里,有许多琼花,环绕着中间的凉亭。
有 N 片琼花,组成一个环。
Ninian 想在凉亭中发动 [セチの祈り] , 需要划分出三个区域的琼花,为了平均,要最大化面积最小的区域的面积。
划分区域:即用三刀把这个环分成三段,每段称之为一个区域。
题解:
就会这一题写一下题解吧。。。
如果不是环形的话,显然二分+O(n)判断就可以,因为满足单调性。
如果是环形,我们需要枚举起点,所以复杂度成了n*n*logn
但是我们考虑优化判断的时间复杂度,因为a是一个单调递增的数组,所以我们照样可以lower_bound下一段>当前二分值的区间。复杂度变为n*log2n
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #include<string> 12 #define inf 1000000000 13 #define maxn 200000+100 14 #define maxm 500+100 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define mod 1000000007 23 using namespace std; 24 inline ll read() 25 { 26 ll x=0,f=1;char ch=getchar(); 27 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 28 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 29 return x*f; 30 } 31 int n; 32 ll a[2*maxn]; 33 inline bool check(ll x,int y) 34 { 35 int xx=lower_bound(a+y,a+y+n,a[y-1]+x)-a; 36 if(xx>=y+n)return 0; 37 int yy=lower_bound(a+xx+1,a+y+n,a[xx]+x)-a; 38 if(yy>=y+n)return 0; 39 return a[n+y-1]-a[yy]>=x; 40 } 41 int main() 42 { 43 freopen("input.txt","r",stdin); 44 freopen("output.txt","w",stdout); 45 n=read();ll sum=0; 46 for1(i,n)a[i]=a[n+i]=read(),sum+=a[i]; 47 for1(i,n<<1)a[i]+=a[i-1]; 48 ll ans=0; 49 for1(i,n) 50 { 51 if(!check(ans,i))continue; 52 ll l=ans,r=sum,mid; 53 while(l<=r) 54 { 55 mid=(l+r)>>1; 56 if(!check(mid,i))r=mid-1;else l=mid+1; 57 } 58 ans=max(ans,r); 59 } 60 printf("%lld ",ans); 61 return 0; 62 }