[CQOI2011]动态逆序对

带修主席树。
脑补一下,每个数对逆序对数的贡献就是前面的比它大的加上后面的比它小的,这样就可以套带修主席树的板子,找一下在它前面删去的比它大的,找一下在它后面比它小的数的个数就行了。
UPD:BZOJ上T了,发现t[]开的太大了,memset的时候直接挂。。。认真算空间Orz

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=100005;
int n,m,a[N],t[N*10],f[N],pos[N],g[N],x[N],y[N],rt[N];
long long ans;
void add(int x) {
    for(int i=x;i<=n;i+=i&-i) t[i]++;
}
int ask(int x) {
    int ans=0;  
    for(int i=x;i;i-=i&-i) ans+=t[i];
    return ans;
}
int tot,ls[N*100],rs[N*100],siz[N*100];
void update(int &k,int l,int r,int val) {
    if(!k)k=++tot;siz[k]++;
    int mid=l+r>>1;
    if(l==r) return;
    if(val<=mid) update(ls[k],l,mid,val);
    else update(rs[k],mid+1,r,val);
}
int queryx(int L,int R,int val) {
    int totx=0,toty=0,ans=0;L--;
    int l=1,r=n;
    for(int i=L;i;i-=i&-i) x[++totx]=rt[i];
    for(int i=R;i;i-=i&-i) y[++toty]=rt[i];
    while(l!=r) {
        int mid=l+r>>1;
        if(val<=mid) {
            for(int i=1;i<=totx;i++) ans-=siz[rs[x[i]]],x[i]=ls[x[i]];
            for(int i=1;i<=toty;i++) ans+=siz[rs[y[i]]],y[i]=ls[y[i]];
            r=mid;
        }
        else {
            for(int i=1;i<=totx;i++) x[i]=rs[x[i]];
            for(int i=1;i<=toty;i++) y[i]=rs[y[i]];
            l=mid+1;
        }
    } 
    return ans;
}
int queryd(int L,int R,int val) {
    int totx=0,toty=0,ans=0;L--;
    int l=1,r=n;
    for(int i=L;i;i-=i&-i) x[++totx]=rt[i];
    for(int i=R;i;i-=i&-i) y[++toty]=rt[i];
    while(l!=r) {
        int mid=l+r>>1;
        if(val>mid) {
            for(int i=1;i<=totx;i++) ans-=siz[ls[x[i]]],x[i]=rs[x[i]];
            for(int i=1;i<=toty;i++) ans+=siz[ls[y[i]]],y[i]=rs[y[i]];
            l=mid+1;
        }
        else {
            for(int i=1;i<=totx;i++) x[i]=ls[x[i]];
            for(int i=1;i<=toty;i++) y[i]=ls[y[i]];
            r=mid;
        }
    }
    return ans;
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),f[i]=ask(n)-ask(a[i]),add(a[i]),ans+=f[i],pos[a[i]]=i;
    memset(t,0,sizeof t);
    for(int i=n;i;i--) {
        g[i]=ask(a[i]);
        add(a[i]);
    }
    int u;
    for(int i=1;i<=m;i++) {
        printf("%lld\n",ans);
        scanf("%d",&u);
        u=pos[u];
        ans-=(f[u]+g[u]-queryx(1,u-1,a[u])-queryd(u+1,n,a[u]));
        for(int j=u;j<=n;j+=j&-j) update(rt[j],1,n,a[u]);
    }
    return 0;
}
posted @ 2018-08-19 21:03  SWHsz  阅读(157)  评论(0编辑  收藏  举报