POJ 3928 Ping Pong

来源:互联网 发布:老子的道是指什么 知乎 编辑:程序博客网 时间:2024/05/19 19:58
初学树状数组,水水的A了一下,具体解释见代码
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>using namespace std;int t,n,maxnum;const int maxm=100000+100;const int maxn=20000+10;int g[maxm],h[maxm];int a[maxn],c[maxn],d[maxn];int lowbit(int x){    return x&(-x);}void add(int x,int f[])//是不是一定要是全局数组{    while(x<=maxnum)//也可以是maxm,不过那样的话好像更费时间,有些用不到的地方也加了1    {        f[x]++;        x+=lowbit(x);    }}//这样初始化有问题,f虽然是地址,但是却是指针,size只有4字节//void init(int *f)//{//    printf("in init:%d\n",f);//    memset(f,0,sizeof(f));//    printf("fsize:%d\n",sizeof(f));//    for(int i=0;i<n;i++)//        printf("%d",f[i]);//     printf("\n");//}int sum(int x,int f[]){    int ret=0;    while(x>0)    {        ret+=f[x];        x-=lowbit(x);    }    return ret;}int main(){//  生成随机数测试//    freopen("test.txt","w",stdout);//    srand((unsigned)time(NULL));//    t=rand()%10+1;////    printf("%d\n\n",t);//    while(t--)//    {//        n=rand()%20+1;//        printf("%d\n",n);//        for(int i=1;i<=n;i++)//        {//            int number=rand()%1000+1;//            printf("%d ",number);//        }//    printf("\n\n");//    }//    return 0;//    freopen("test.txt","r",stdin);//     freopen("out.txt","w",stdout);    scanf("%d",&t);    while(t--)    {//        printf("in main:%d\n",a);        scanf("%d",&n);//        init(a),init(c),init(d),init(g),init(h);这样初始化不对        memset(a,0,sizeof(a));        memset(c,0,sizeof(c));        memset(d,0,sizeof(d));        memset(g,0,sizeof(g));        memset(h,0,sizeof(h));        maxnum=0;        for(int i=1;i<=n;i++)           {            scanf("%d",&a[i]);            maxnum=max(maxnum,a[i]);           }        add(a[1],g);//把树状数组中包含a[1]的长条的值+1        for(int i=2;i<=n;i++)        {            c[i]=sum(a[i],g);//第i个数的左边有c[i]个比a[i]小            add(a[i],g);//把树状数组中包含a[i]的长条的值+1        }        add(a[n],h);        for(int i=n-1;i>=1;i--)        {            d[i]=sum(a[i],h);//第i个数的右边有d[i]个比a[i]小            add(a[i],h);        }        long long ans=0;        for(int i=1;i<=n;i++)           ans+=(long long)c[i]*(n-i-d[i])+(long long)d[i]*(i-1-c[i]);        printf("%lld\n",ans);    }    return 0;}