题意:给定一个长为n的序列,求序列上任取一段非空子区间,其区间内的数的平均值在L~R之间的期望。(n<=5e5,区间数的权值及l,r均在100以内)
做法:显然是计数问题,先推一波式子,对序列做前缀和后所求变为:
求满足L(r-l+1)<=sum[r]-sum[l-1]<=R(r-l+1) 的l,r对数
移项化简,得到所求变为:sum[l-1]-(l-1)R>=sum[r]-r*R,sum[l-1]-(l-1)L<=sum[r]-r*L。
做到这一步我们可以发现,可以对位置i维护两个值f[i],g[i],
f[i]=sum[i]-i*L,g[i]=sum[i]-i*R.
所求变为:
求满足i>j,且f[i]>=f[j],且g[i]<=g[j]的i,j对数。
这不是裸的三维偏序吗,可是你会发现这题数据范围5e5,(忘说了时限1s),nlog^2n跑不过的...
但我们可以发现,直接这样化简损失了一些f数组和g数组之间的关系:
g[i]=f[i]-(R-L)*i
假设两位置i,j(i>j)其f[i]<f[j](即不满足f[i]>=f[j])
那么带入我们忽略的f,g关系可得:
g[i]=f[i]-(R-L)i
g[j]=f(j)-(R-L)j
而f[i]<f[j] i>j R>=L
所以此时g[i]<g[j] !!!
同理可推g[i]>g[j]。
所以发现不满足f性质的一定满足g性质,不满足g性质的一定满足f性质。
所以只要算每个位置的贡献减去不满足f性质的和不满足g性质的即可,变成一个二维偏序,直接树状数组。。
(注意下最早的原式中是l-1~r,所以处理的时候要把0放入)。
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e5+10;
void read(int &x)
{
char c=getchar();x=0;bool f=0;
while(!isdigit(c))f|=(c=='-'),c=getchar();
while(isdigit(c))x=x*10+c-48,c=getchar();
if(f)x=-x;
}
int a[N],sum[N],n,f[N],g[N],tax[N],L,R;
ll ans=0;
struct BIT{
int tr[N];
int ask(int x)
{
int res=0;
for(;x;x-=x&-x)res+=tr[x];
return res;
}
void add(int x)
{for(;x<=n+5;x+=x&-x)tr[x]++;}
int ask(int l,int r)
{return ask(r)-ask(l-1);}
}t1,t2;
ll gcd(ll x,ll y)
{return !y?x:gcd(y,x%y);}
int main()
{
read(n),read(L),read(R);
for(int i=1;i<=n;i++)
read(a[i]);
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
for(int i=0;i<=n;i++)
f[i]=sum[i]-i*L,g[i]=sum[i]-i*R,tax[i]=f[i];
sort(tax,tax+n+1);
int len=unique(tax,tax+n+1)-tax;
for(int i=0;i<=n;i++)
f[i]=1+lower_bound(tax,tax+len+1,f[i])-tax;
for(int i=0;i<=n;i++)
tax[i]=g[i];
sort(tax,tax+n+1);
len=unique(tax,tax+n+1)-tax;
for(int i=0;i<=n;i++)
g[i]=1+lower_bound(tax,tax+len+1,g[i])-tax;
for(int i=0;i<=n;i++)
{
if(i!=0)ans+=i-t1.ask(f[i]+1,n+5)-t2.ask(g[i]-1);
t1.add(f[i]),t2.add(g[i]);
}
ll tot,L;
tot=1LL*n*(n+1)/2LL;
L=gcd(ans,tot);
ans/=L,tot/=L;
if(ans==0)return puts("0"),0;
if(ans==tot)return puts("1"),0;
printf("%lld/%lld",ans,tot);
}