• P3157 [CQOI2011]动态逆序对(树状数组套线段树)


    P3157 [CQOI2011]动态逆序对

    树状数组套线段树

    静态逆序对咋做?树状数组(别管归并QWQ)

    然鹅动态的咋做?

    我们考虑每次删除一个元素。

    减去的就是与这个元素有关的逆序对数,介个可以预处理:从左到右求一次,再倒过来求一次,用2个数组存起来。

    但是前面已经删除的元素与当前删除元素组成的逆序对会被重复计数。

    于是考虑再减去重复计数

    我们用树状数组套线段树(动态开点):

    第$i$棵线段树 储存 每个位置在$i$之前的被删除元素

    蓝后每次查询时左边右边找一找

    把它们加回来就好辣

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    void read(int &x){
        static char c=getchar();x=0;
        while(c<'0'||c>'9') c=getchar();
        while('0'<=c&&c<='9') x=x*10+(c^48),c=getchar();
    }
    #define W 6000005
    #define N 100005
    int n,m,u,pos[N],id[N],s[N];
    int rt[N],sum[W],lc[W],rc[W];
    ll ans,L[N],R[N];
    void T_Add(int x,int v){for(;x<=n;x+=x&-x)s[x]+=v;}
    int T_Sum(int x){int re=0; for(;x;x-=x&-x)re+=s[x]; return re;}
    #define mid (l+r)/2
    void S_Add(int &o,int l,int r,int x){
        if(!o) o=++u;
        ++sum[o];
        if(l==r) return;
        if(x<=mid) S_Add(lc[o],l,mid,x);
        else S_Add(rc[o],mid+1,r,x);
    }
    int S_Sum(int o,int l,int r,int x1,int x2){
        if(x1<=l&&r<=x2) return sum[o];
        int re=0;
        if(x1<=mid) re+=S_Sum(lc[o],l,mid,x1,x2);
        if(x2>mid) re+=S_Sum(rc[o],mid+1,r,x1,x2);
        return re;
    }
    ll S_Find(int l,int r,int x1,int x2){//查询l+1~r内所有范围在x1~x2的个数
        if(x1>x2) return 0;
        ll re=0;
        for(int i=r;i;i-=i&-i) re+=(ll)S_Sum(rt[i],1,n,x1,x2);
        for(int i=l;i;i-=i&-i) re-=(ll)S_Sum(rt[i],1,n,x1,x2);
        return re;
    }
    int main(){
        read(n);read(m); register int i,j; int q,p;
        for(i=1;i<=n;++i){
            read(pos[i]); id[pos[i]]=i;
            L[i]=T_Sum(n)-T_Sum(pos[i]);
            ans+=L[i]; T_Add(pos[i],1);
        }memset(s,0,sizeof(s));
        for(i=n;i;--i) R[i]=T_Sum(pos[i]-1),T_Add(pos[i],1);
        for(i=1;i<=m;++i){
            printf("%lld
    ",ans); read(q); p=id[q];
            ans-=L[p]+R[p]-S_Find(0,p,q+1,n)-S_Find(p,n,1,q-1);
            for(j=p;j<=n;j+=j&-j) S_Add(rt[j],1,n,q);
        }return 0;
    }
  • 相关阅读:
    Python爬虫 Urllib库的高级用法
    Python爬虫入门 Urllib库的基本使用
    Oracle wm_concat()函数
    linux cut命令详解
    linux sort命令详解(转)
    linux awk 命令详解
    linux sed命令详解
    Oracle 数据导入导出操作 (转)
    sqlldr用法
    Python os与sys模块解析
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10586547.html
Copyright © 2020-2023  润新知