1. 程式人生 > >BZOJ3295:[CQOI2011]動態逆序對

BZOJ3295:[CQOI2011]動態逆序對

淺談樹狀陣列與線段樹:https://www.cnblogs.com/AKMer/p/9946944.html

題目傳送門:https://www.lydsy.com/JudgeOnline/problem.php?id=3295

樹狀陣列套線段樹,如題目所言,動態維護答案即可。

寫了樹套樹之後我才發現遞迴是個多麼傻逼的玩意兒……

時間複雜度:\(O(nlog^2n)\)

空間複雜度:\(O(nlogn)\)

程式碼如下:

#include <cstdio>
using namespace std;
typedef long long ll;
#define low(i) ((i)&(-(i)))

const int maxn=1e5+5;

ll ans;
int n,m;
int pos[maxn];

inline int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

struct segment_tree {
    int tot;
    int ls[maxn*85],rs[maxn*85],sum[maxn*85];

    inline int query(int p,int l,int r,int pos,int opt) {
        int res=0;
        while(l!=r) {
            int mid=(l+r)>>1;
            if(pos<=mid) {
                if(opt)res+=sum[rs[p]];
                p=ls[p],r=mid;
            }
            else {
                if(!opt)res+=sum[ls[p]];
                p=rs[p],l=mid+1;
            }
        }
        return res;
    }

    inline void change(int p,int l,int r,int pos,int v) {
        if(!p)p=++tot;
        while(1) {
            sum[p]+=v;if(l==r)break;
            int mid=(l+r)>>1;
            if(pos<=mid) {
                if(!ls[p])ls[p]=++tot;
                p=ls[p],r=mid;
            }
            else {
                if(!rs[p])rs[p]=++tot;
                p=rs[p],l=mid+1;
            }
        }
    }
}T;

struct TreeArray {
    int rt[maxn];

    inline int query(int pos,int v,int opt) {
        int res=0;
        for(int i=pos;i;i-=low(i))
            res+=T.query(rt[i],1,n,v,opt);
        return res;
    }

    inline void change(int pos,int x,int v) {
        for(int i=pos;i<=n;i+=low(i)) {
            if(!rt[i])rt[i]=++T.tot;
            T.change(rt[i],1,n,x,v);
        }
    }
}bit;

int main() {
    n=read(),m=read();
    for(int i=1;i<=n;i++) {
        int x=read();pos[x]=i;
        ans+=bit.query(i-1,x,1);
        bit.change(i,x,1);
    }
    for(int i=1;i<=m;i++) {
        printf("%lld\n",ans);
        int x=read();
        ans-=bit.query(pos[x]-1,x,1);
        ans-=bit.query(n,x,0)-bit.query(pos[x],x,0);
        bit.change(pos[x],x,-1);
    }
    return 0;
}