平均值

源代码:

#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[]的逆序对数,以此类推,注意细节。
*/
posted @ 2016-10-30 10:16  前前前世。  阅读(212)  评论(0编辑  收藏  举报