hdu 5792 World is Exploding 树状数组

来源:互联网 发布:linux下php言编程ide 编辑:程序博客网 时间:2024/05/16 09:55

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

#include<iostream>#include<cstdio>#include<cstdlib>#include<vector>#include<cmath>#include<string>#include<algorithm>#include<set>#include<map>#include<cstring>#include<queue>#include<stack>#include<list>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;typedef long long ll;const int maxn=50000+1000;const ll inf=1e9;const ll mod=1e9+7;int a[maxn];int b[maxn];ll Li[maxn],La[maxn],Ri[maxn],Ra[maxn];int cnt[maxn];int bit[maxn];int sum(int i){    int s=0;    while(i>0){        s+=bit[i];        i-=i&-i;    }    return s;}void add(int i,int x){    while(i<maxn){        bit[i]+=x;        i+=i&-i;    }}int main(){    int n;    while(~scanf("%d",&n)){        for(int i=0;i<n;i++){            scanf("%d",&a[i]);            b[i]=a[i];        }        sort(b,b+n);        int m=unique(b,b+n)-b;        for(int i=0;i<n;i++){            a[i]=lower_bound(b,b+m,a[i])-b;            a[i]+=1;            //cout<<a[i]<<endl;        }        ll la=0,lb=0;        memset(cnt,0,sizeof(cnt));        memset(bit,0,sizeof(bit));        for(int i=0;i<n;i++){            Li[i]=sum(a[i]-1);            La[i]=i-Li[i]-cnt[a[i]];            add(a[i],1);            cnt[a[i]]++;            la+=Li[i];        }        memset(cnt,0,sizeof(cnt));        memset(bit,0,sizeof(bit));        for(int i=n-1;i>=0;i--){            Ri[i]=sum(a[i]-1);            Ra[i]=n-1-i-Ri[i]-cnt[a[i]];            add(a[i],1);            cnt[a[i]]++;            lb+=Ri[i];        }        ll ans=la*lb;        for(int i=0;i<n;i++){            ans=ans-Ri[i]*Ra[i];            ans=ans-Li[i]*La[i];            ans=ans-Li[i]*Ri[i];            ans=ans-La[i]*Ra[i];        }        printf("%I64d\n",ans);    }return 0;}


0 0
原创粉丝点击