bzoj3295: [Cqoi2011]动态逆序对

来源:互联网 发布:淘宝一元云购是真的吗 编辑:程序博客网 时间:2024/05/23 12:34

传送门
树状数组套主席树。
外层树状数组记录区间
内层主席树记录数字出现个数
删减时枚举在前面比他小的删去的点的数量
和在后面比他大的删去的点的数量
求值可以用树状数组实现。
时间复杂度nlogn^2

#include<cstdio>#include<cstdlib>#include<iostream>#include<cmath>#include<cstring>#include<algorithm>#define inf 0x3f3f3f3f#define ll long long#define N 100005#define M 5000005using namespace std;ll ans;int n,m,sz,x;int a[35],b[35];int num[N],pos[N],a1[N],a2[N],t[N],rt[N];int ls[M],rs[M],sum[M];inline int ask(int x){    int s=0;    for (int i=x;i;i-=i&(-i))        s+=t[i];    return s;}void change(int &y,int l,int r,int x){    if (!y) y=++sz;    sum[y]++;    if (l==r) return;    int mid=(l+r)/2;    if (x<=mid) change(ls[y],l,mid,x);    else change(rs[y],mid+1,r,x);}int askmore(int x,int y,int num){    a[0]=b[0]=0;    int tmp=0;    for (int i=x-1;i;i-=i&(-i))        a[++a[0]]=rt[i];    for (int i=y;i;i-=i&(-i))        b[++b[0]]=rt[i];    int l=1,r=n;    while (l<r){        int mid=(l+r)/2;        if (num<=mid){            for (int i=1;i<=a[0];i++) tmp-=sum[rs[a[i]]];            for (int i=1;i<=b[0];i++) tmp+=sum[rs[b[i]]];            for (int i=1;i<=a[0];i++) a[i]=ls[a[i]];            for (int i=1;i<=b[0];i++) b[i]=ls[b[i]];            r=mid;        }        else{            for (int i=1;i<=a[0];i++) a[i]=rs[a[i]];            for (int i=1;i<=b[0];i++) b[i]=rs[b[i]];            l=mid+1;        }    }    return tmp;}int askless(int x,int y,int num){    a[0]=b[0]=0;    int tmp=0;    for (int i=x-1;i;i-=i&(-i))        a[++a[0]]=rt[i];    for (int i=y;i;i-=i&(-i))        b[++b[0]]=rt[i];    int l=1,r=n;    while (l<r){        int mid=(l+r)/2;        if (num>mid){            for (int i=1;i<=a[0];i++) tmp-=sum[ls[a[i]]];            for (int i=1;i<=b[0];i++) tmp+=sum[ls[b[i]]];            for (int i=1;i<=a[0];i++) a[i]=rs[a[i]];            for (int i=1;i<=b[0];i++) b[i]=rs[b[i]];            l=mid+1;        }        else{            for (int i=1;i<=a[0];i++) a[i]=ls[a[i]];            for (int i=1;i<=b[0];i++) b[i]=ls[b[i]];            r=mid;        }    }    return tmp;}int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=n;i++){        scanf("%d",&num[i]);        pos[num[i]]=i;        a1[i]=ask(n)-ask(num[i]);        ans+=a1[i];        for (int j=num[i];j<=n;j+=j&(-j))            t[j]++;    }    memset(t,0,sizeof(t));    for (int i=n;i>=1;i--){        a2[i]=ask(num[i]-1);        for (int j=num[i];j<=n;j+=j&(-j))            t[j]++;     }    for (int i=1;i<=m;i++){        printf("%lld\n",ans);        scanf("%d",&x); x=pos[x];        ans-=(a1[x]+a2[x]-askmore(1,x-1,num[x])-askless(x+1,n,num[x]));        for (int j=x;j<=n;j+=j&(-j))            change(rt[j],1,n,num[x]);    }}
0 0
原创粉丝点击