uva11990 线段树套树状数组

来源:互联网 发布:海信ip906h安装软件 编辑:程序博客网 时间:2024/05/21 11:11

题意:给一个1-n的排列,按照某种顺序一些数(其他数顺序不变),输出每次删除之前逆序对的数目。

分析:线段树每个节点表示的一段数字排序,每个节点用树状数组维护删除的点。

#include<iostream>#include<string>#include<cstring>#include<cstdio>#include<cmath>#include<iomanip>#include<map>#include<algorithm>#include<queue>#include<set>#define inf 1000000000#define pi acos(-1.0)#define eps 1e-8#define seed 131using namespace std;typedef pair<int,int> pii;typedef unsigned long long ull;typedef long long ll;const int maxn=200005;int n,m;int order[30][maxn];int tree[30][maxn];int pos[maxn];ll ans;int lowbit(int x){    return x&-x;}int getSum(int* s,int x,int o){    int sum=0;    while(x>o) {        sum+=s[x];        x-=lowbit(x);    }    return sum;}void update(int* s,int v,int x,int o){    while(x<=o) {        s[x]+=v;        x+=lowbit(x);    }}void build(int l,int r,int rt,int d){    for(int i=l;i<=r;i++) {        order[d][i]=order[d-1][i];        tree[d][i]=0;    }    if(l==r) return;    int m=(l+r)/2;    build(l,m,rt<<1,d+1);    build(m+1,r,rt<<1|1,d+1);    sort(order[d]+l,order[d]+r+1);}void query(int l,int r,int x,int flag,int d,int L,int R,int rt){    if(l>r)        return;    if(l<=L&&r>=R) {        int k=lower_bound(order[d]+L,order[d]+R+1,x)-order[d];        if(k>R||order[d][k]>x) {            k--;        }        int u=getSum(tree[d],k,L-1);        if(flag) {            k=k-L+1;            ans-=k-u;        }        else {            int v=getSum(tree[d],R,L-1);            v-=u;            ans-=R-k-v;        }        return;    }    int m=(L+R)/2;    if(l<=m){        query(l,r,x,flag,d+1,L,m,rt<<1);    }    if(r>m) {        query(l,r,x,flag,d+1,m+1,R,rt<<1|1);    }}void Update(int l,int x,int d,int L,int R,int rt){    if(l==L&&l==R) {        update(tree[d],1,l,R);        return;    }    int m=(L+R)/2;    if(l<=m) {        Update(l,x,d+1,L,m,rt<<1);    }    else {        Update(l,x,d+1,m+1,R,rt<<1|1);    }    int k=lower_bound(order[d]+L,order[d]+R+1,x)-order[d];    update(tree[d],1,k,R);}int main(){    int x;    while(~scanf("%d%d",&n,&m)) {        memset(tree[0],0,sizeof(tree[0]));        ans=0;        for(int i=1;i<=n;i++) {            scanf("%d",&order[0][i]);            pos[order[0][i]]=i;            ans+=i-1-getSum(tree[0],order[0][i],0);            update(tree[0],1,order[0][i],n);        }        build(1,n,1,1);        for(int i=0;i<m;i++) {            scanf("%d",&x);            printf("%lld\n",ans);            query(1,pos[x]-1,x,0,1,1,n,1);            query(pos[x]+1,n,x,1,1,1,n,1);            Update(pos[x],x,1,1,n,1);        }    }    return 0;}


0 0
原创粉丝点击