PoPoQQQ大爷:
看到平均值最大果断二分答案
看到长度[L,R]果断单调队列
维护一个前缀和的单调递增队列,枚举到i把i-L进队i-R之前的出队
然后长度为偶数分开维护两个单调队列即可
似乎此题犯了我好多sb错误 ,各种不同姿势的tle
二分答案一定要用long double
二分答案一定要用long double
二分答案一定要用long double
重要的事说三遍!!
#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define T 220006
#define MX 1e9
#define pa pair<int,int>
using namespace std;
long double sum[T];
int a[T];
int n,L,R,mx;
int q[2][T],l[2],r[2];
long long ans;
int sc()
{
int i=0,f=1; char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
return i*f;
}
long long gcd(long long x,long long y){return x==0?y:gcd(y%x,x);}
bool jud(long double y)
{
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i]-y;
l[0]=l[1]=1; r[0]=r[1]=0;
for(int i=L;i<=n;i++)
{
int w=i&1,x=i-L;
while(r[w]>=l[w]&&sum[x]<sum[q[w][r[w]]])r[w]--;
while(r[w]>=l[w]&&q[w][l[w]]<i-R)l[w]++;
q[w][++r[w]]=x;
if(sum[i]-sum[q[w][l[w]]]>=0) return ans=i-q[w][l[w]];
}
return 0;
}
int main()
{
n=sc(),L=sc(),R=sc();
for(int i=1;i<=n;i++)a[i]=sc(),mx=max(mx,a[i]);
for(int i=1;i<=n;i++)a[i+n]=a[i];
if(L&1)L++;if(R&1)R--;n*=2;
long double l=0,r=mx;
while(r-l>1e-7)
{
long double mid=(l+r)/2;
if(jud(mid))l=mid;
else r=mid;
}
long double x=(l+r)/2;
long long w=(long long)(ans*x+0.5);
long long Gcd=gcd(w,ans);
w/=Gcd;ans/=Gcd;
if(ans==1)cout<<w; else cout<<w<<"/"<<ans;
return 0;
}