先处理出前缀和 sumi
区间 [l..r] 的几乎平均数为
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 100005
#define LL long long
using namespace std;
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;
}
struct W{int l,r;}f[310][N];
long long sum[N];
int n,m,block,id[333],bl[N],q[N];
double slop(int x,int y)
{
return (double)(sum[x]-sum[y])/(x-y);
}
double slop1(int x,int y)
{
return (double)(sum[x-1]-sum[y-1])/(x-y);
}
double cal(int l,int r)
{
return (double)(sum[r]-sum[l-1])/(r-l);
}
long long gcd(LL x,LL y)
{
return x==0?y:gcd(y%x,x);
}
void print(int l,int r)
{
long long x=sum[r]-sum[l-1],y=r-l,p=gcd(abs(x),abs(y));
printf("%lld/%lld\n",x/p,y/p);
}
void solve(int l,int r)
{
double mx=-11111111111.0;
int ql=n,qr=n-1,lx,rx;
for(int i=r;i>l;i--)
{
while(ql5)
{
int Lmid=L+(R-L)/3;
int Rmid=R-(R-L)/ 3;
if(cal(i-1,q[Lmid])>cal(i-1,q[Rmid]))
R=Rmid;
else L=Lmid;
}
for(int j=L;j<=R;j++)
{
double now=cal(i-1,q[j]);
if(now>mx) mx=now,lx=i-1,rx=q[j];
}
}
print(lx,rx);
}
void pre()
{
for(int i=1;i<=bl[n];i++)
{
int x=id[i],ql=n,qr=n-1;
double ans=-111111111111.0;
for(int j=x-1;j>=1;j--)
{
f[i][j]=f[i][j+1];
while(ql1,q[ql])1,q[ql+1]))ql++;
q[--ql]=j+1;
int L=ql,R=qr;
while(R-L>5)
{
int Lmid=L+(R-L)/3;
int Rmid=R-(R-L)/3;
if(cal(j,q[Lmid])>cal(j,q[Rmid]))
R=Rmid;
else L=Lmid;
}
for(int k=L;k<=R;k++)
{
double now=cal(j,q[k]);
if(now>ans)
{
ans=now;
f[i][j].l=j;
f[i][j].r=q[k];
}
}
}
ql=1,qr=0; ans=-111111111111.0;
for(int j=x+1;j<=n;j++)
{
f[i][j]=f[i][j-1];
while(qlq[qr],j-1)q[qr-1],j-1))qr--;
q[++qr]=j-1;
int L=ql,R=qr;
while(R-L>5)
{
int Lmid=L+(R-L)/3;
int Rmid=R-(R-L)/3;
if(cal(q[Lmid],j)>cal(q[Rmid],j))
R=Rmid;
else L=Lmid;
}
for(int k=L;k<=R;k++)
{
double now=cal(q[k],j);
if(now>ans)
{
ans=now;
f[i][j].l=q[k];
f[i][j].r=j;
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+sc();
block=n/sqrt(m);
for(int i=1;i<=n;i++)
{
bl[i]=(i-1)/block+1;
if(bl[i]!=bl[i-1]) id[bl[i]]=i;
}
pre();
while(m--)
{
int l=sc(),r=sc();
if(bl[r]-bl[l]<=1) solve(l,r);
else
{
int ll=bl[l]+1,rr=bl[r];
int lx,rx;
double a1=cal(f[ll][r].l,f[ll][r].r);
double a2=cal(f[rr][l].l,f[rr][l].r);
double ans;
if(a1>a2)
{
lx=f[ll][r].l;
rx=f[ll][r].r;
ans=a1;
}
else
{
lx=f[rr][l].l;
rx=f[rr][l].r;
ans=a2;
}
int ql=n,qr=n-1;
for(int i=r;bl[i]==rr;i--)
{
while(qlq[ql])q[ql+1]))ql++;
q[--ql]=i;
}
for(int i=l;bl[i]int L=ql,R=qr;
while(R-L>5)
{
int Lmid=L+(R-L)/3;
int Rmid=R-(R-L)/3;
if(cal(i,q[Lmid])>cal(i,q[Rmid]))
R=Rmid;
else L=Lmid;
}
for(int k=L;k<=R;k++)
{
double now=cal(i,q[k]);
if(now>ans) ans=now,lx=i,rx=q[k];
}
}
print(lx,rx);
}
}
return 0;
}