返回顶部

AcWing 241.楼兰图腾 (树状数组,逆序对)

  • 题意:在二维坐标轴上给你一些点,求出所有由三个点构成的v和∧图案的个数.

  • 题解:因为给出的点是按横坐标的顺序给出的,所以我们可以先遍历然后求出某个点左边比它高和低的点的个数(这个过程简直和用树状数组求逆序对的操作一模一样好不好!),用\(grt[i]\)记录第\(i\)个点左边比它大的数,\(low[i]\)表示比它小的数,然后我们再对树状数组清空,反着求一下每个点右边的情况,这次不用再记录了,直接求贡献给答案即可.

  • 代码:

    #define int long long
     
    int n;
    int a[N];
    int c[N];
    int grt[N],low[N];
    int res1,res2;
    
    int lowbit(int x){
        return x&(-x);
    }
    
    void updata(int i,int k){
        while(i<=n){
            c[i]+=k;
            i+=lowbit(i);
        }
    }
    
    int get_sum(int i){
        int res=0;
        while(i){
            res+=c[i];
            i-=lowbit(i);
        }
        return res;
    }
    
    signed main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        cin>>n;
        rep(i,1,n) cin>>a[i];
    
        rep(i,1,n){     //每个点左边的greater和lower
            int cur=a[i];
            grt[i]=get_sum(n)-get_sum(cur);
            low[i]=get_sum(cur-1);
            updata(cur,1);
        }
    
        me(c,0,sizeof(c));
    
        per(i,n,1){    //求每个点右边的greater和lower,以及更新答案
            int cur=a[i];
            res1+=grt[i]*(get_sum(n)-get_sum(cur));
            res2+=low[i]*get_sum(cur-1);
            updata(cur,1);
        }
    
        cout<<res1<<' '<<res2;
     
        return 0;
    }
    
posted @ 2020-11-16 21:45  Rayotaku  阅读(77)  评论(0编辑  收藏  举报