首页 > 代码库 > P1894セチの祈り

P1894セチの祈り

描述

在 Ninian 的花园里,有许多琼花,环绕着中间的凉亭。
有 N 片琼花,组成一个环。
Ninian 想在凉亭中发动 [セチの祈り] , 需要划分出三个区域的琼花,为了平均,要最大化面积最小的区域的面积。

划分区域:即用三刀把这个环分成三段,每段称之为一个区域。

题解:
就会这一题写一下题解吧。。。
如果不是环形的话,显然二分+O(n)判断就可以,因为满足单调性。
如果是环形,我们需要枚举起点,所以复杂度成了n*n*logn 
但是我们考虑优化判断的时间复杂度,因为a是一个单调递增的数组,所以我们照样可以lower_bound下一段>当前二分值的区间。复杂度变为n*log2n
代码:
 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 100000000013 #define maxn 200000+10014 #define maxm 500+10015 #define eps 1e-1016 #define ll long long17 #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 100000000723 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\n",ans);61     return 0;62 }
View Code

 

 

P1894セチの祈り