hdu 2492 Ping pong (树状数组)

理解对了了题意的话应该算是道简单的树状数组。

题目要求裁判不能同时低于两个人,或者同时高于两人。就是求一个长度为3的顺序序列。

这样的话对于第i个数ai,我们可以求出左边比ai大的数lmaxi,右边比ai小的数rmini.相乘再加上反过来左边小右边大的情况就是结果。




#include <iostream>
#include<cstdio>
#include<cstring>
#define maxm 100001
#define clr(A,k) memset(A,(k),sizeof(A))
#define LL long long
using namespace std;
int C[maxm],A[maxm];
int lmin[maxm],rmin[maxm],lmax[maxm],rmax[maxm];
void init(){
    for(int i=0;i<maxm;i++){
        C[i]=0;
        lmin[i]=0;
        lmax[i]=0;
        rmin[i]=0;
        rmax[i]=0;
    }
}
int lowbit(int x){
    return x&(-x);
}
void update(int pos,int val){
    while(pos<=maxm){
        C[pos]+=val;
        pos+=lowbit(pos);
    }
}
int query(int x){
    int ret=0;
    while(x>0){
        ret+=C[x];
        x-=lowbit(x);
    }
    return ret;
}
int main()
{
    int T,N;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N);
        for(int i=1;i<=N;i++){
            scanf("%d",&A[i]);
        }
        init();
        for(int i=1;i<=N;i++){
            update(A[i],1);
            int tmp=query(A[i]-1);
            lmin[i]=tmp;
            lmax[i]=i-tmp-1;//返回左边比A[i]大的数
        }
        clr(C,0);
        for(int i=N,j=1;i>=1;i--,j++){
            update(A[i],1);
            int tmp=query(A[i]-1);
            rmin[i]=tmp;
            rmax[i]=j-tmp-1;
        }
        LL sum=0;
        for(int i=1;i<=N;i++){
            sum+=lmin[i]*rmax[i]+lmax[i]*rmin[i];
        }
        printf("%I64d\n",sum);
    }
    return 0;
}


你可能感兴趣的:(hdu 2492 Ping pong (树状数组))