源代码:
#include<cstdio>
int n,L,R,Ans,i[500001],j[500001],Sum[500001];
int GCD(int t1,int t2)
{
return t2?GCD(t2,t1%t2):t1;
}
void Merge1(int t1,int t2) //细节的繁琐处理。
{
if (t1==t2)
return;
int X=t1,Y=((t1+t2)>>1)+1,Z=Y-1,Num=t1;
Merge1(X,Z);
Merge1(Y,t2);
while (X<=Z&&Y<=t2)
if (Sum[X]<Sum[Y])
j[Num++]=Sum[X++];
else
{
Ans+=Z-X+1;
j[Num++]=Sum[Y++];
}
while (X<=Z)
j[Num++]=Sum[X++];
while (Y<=t2)
j[Num++]=Sum[Y++];
for (int a=t1;a<=t2;a++)
Sum[a]=j[a];
}
void Merge2(int t1,int t2)
{
if (t1==t2)
return;
int X=t1,Y=((t1+t2)>>1)+1,Z=Y-1,Num=t1;
Merge2(X,Z);
Merge2(Y,t2);
while (X<=Z&&Y<=t2)
if (Sum[X]<=Sum[Y])
j[Num++]=Sum[X++];
else
{
Ans+=Z-X+1;
j[Num++]=Sum[Y++];
}
while (X<=Z)
j[Num++]=Sum[X++];
while (Y<=t2)
j[Num++]=Sum[Y++];
for (int a=t1;a<=t2;a++)
Sum[a]=j[a];
}
int Solve1(int S)
{
Sum[0]=Ans=0;
for (int a=1;a<=n;a++)
{
Sum[a]=Sum[a-1]+i[a]-S;
if (Sum[a]<=0)
Ans++;
}
Merge1(1,n);
return Ans;
}
int Solve2(int S) //为什么不能统一,因为平均数不一定是整数啊!
{
Sum[0]=Ans=0;
for (int a=1;a<=n;a++)
{
Sum[a]=Sum[a-1]+i[a]-S;
if (Sum[a]<0)
Ans++;
}
Merge2(1,n);
return Ans;
}
int main() //凡事还得想想逆序对。
{
scanf("%d%d%d",&n,&L,&R);
for (int a=1;a<=n;a++)
scanf("%d",&i[a]);
int t1=Solve1(R)-Solve2(L);
int t2=n*(n+1)>>1;
if (t1%t2)
{
int t=GCD(t1,t2);
printf("%d/%d",t1/t,t2/t);
}
else
printf("%d",t1/t2);
return 0;
}
/*
题目要求求平均数为[L,R]的区间个数,可以转化为,求平均数为[1,R]区间个数-平均数为[1,L)区间个数。
以[1,R]为例,
(i[a]+i[a+1]+...+i[a+k-1])/k<=R
(i[a]-R)+(i[a+1]-R)+...+(i[a+k-1]-R)<=0
令Sum[]为前缀和数组,
Sum[a+k-1]+Sum[a]<=0
即为求Sum[]的逆序对数,以此类推,注意细节。
*/