HDU 5792 World is Exploding 2016多校赛第五场 树状数组+容斥原理

来源:互联网 发布:苹果系统mac系统下载 编辑:程序博客网 时间:2024/04/30 01:04

点击打开链接

找出有多少个四元组(a,b,c,d)满足a≠b≠c≠d,a < b,c < d,Aa < Ab,Ac > Ad.

思路:

计算像a,b这样上升的有sm对,像c,d这样下降的有bg对,ans=la*lb。这样是有重复的,重复的就是a与c重合,a与d重合,b与c重合,b与d重合这四种情况。那么减去这四种情况就ok了。可以用树状数组预处理出每一位i的左边比a[i]大的有多少Lb[],小的有多少Ls[],右边比a[i]大的有多少Rb[],小的有多少Ls[]。最后ans减去Rs[i]*Rb[i];    Ls[i]*Lb[i];   Ls[i]*Rs[i];   Lb[i]*Rb[i]  就行了。


如何找sm只需从左到右 树状数组 枚举b点,求前面有多少个比他小的,就是sm // ab

找bg只需从右到左 树状数组 枚举c点,求后面有多少个比他小的,就是bg;  //cd

其他的只需要树状数组求即可;

#include<bits/stdc++.h>#define LL long longusing namespace std;const int N=51000;int tree[N];int a[N];int b[N];int cnt[N];int Ls[N],Lb[N],Rs[N],Rb[N];int n;int lowbit(int x){    return x&(-x);}int getsum(int x){    int sum=0;    while(x>0){        sum+=tree[x];        x-=lowbit(x);    }    return sum;}void add(int x,int d){    while(x<=n){        tree[x]+=d;        x+=lowbit(x);    }}int main(){    while(~scanf("%d",&n)){        for(int i=1;i<=n;i++){            scanf("%d",&a[i]);            b[i]=a[i];        }        sort(b+1,b+n+1);        int m=unique(b+1,b+n+1)-b-1;        for(int i=1;i<=n;i++){            a[i]=lower_bound(b+1,b+m+1,a[i])-b;        }        LL sm=0,bg=0;        memset(cnt,0,sizeof(cnt));///重复的点个数        memset(tree,0,sizeof(tree));        memset(Lb,0,sizeof(Lb));        memset(Rb,0,sizeof(Rb));        memset(Ls,0,sizeof(Ls));        memset(Rs,0,sizeof(Rs));        for(int i=1;i<=n;i++){            Ls[i]=getsum(a[i]-1);            Lb[i]=i-1-Ls[i]-cnt[a[i]];            add(a[i],1);            cnt[a[i]]++;            sm+=Ls[i];        }        memset(cnt,0,sizeof(cnt));        memset(tree,0,sizeof(tree));        for(int i=n;i>=1;i--){            Rs[i]=getsum(a[i]-1);            Rb[i]=n-i-Rs[i]-cnt[a[i]];            add(a[i],1);            cnt[a[i]]++;            bg+=Rs[i];        }        LL sum=sm*bg;//        cout<<sum<<endl;//        for(int i=1;i<=n;i++){//            cout<<Lb[i]<<" "<<Ls[i]<<" "<<Rb[i]<<" "<<Rs[i]<<endl;//        }        for(int i=1;i<=n;i++){            sum=sum-Ls[i]*Rs[i];            sum=sum-Ls[i]*Lb[i];            sum=sum-Rs[i]*Rb[i];            sum=sum-Lb[i]*Rb[i];        }        printf("%lld\n",sum);    }    return 0;}


0 0