zoukankan      html  css  js  c++  java
  • bzoj3295 动态逆序对

    Description

    对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

    Input

    输入第一行包含两个整数nm,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。

    Output

    输出包含m行,依次为删除每个元素之前,逆序对的个数。

    将原数列建立归并树,归并树每个节点记录区间排序后结果、被删除的数的个数、树状数组记录前i个数被删了几个,每删除一个数前查找左边比它大的数和右边比它小的数的个数并更新答案。

    #include<cstdio>
    #include<algorithm>
    inline int read(){
        int x=0,c=getchar();
        while(c>57||c<48)c=getchar();
        while(c>47&&c<58)x=x*10+c-48,c=getchar();
        return x;
    }
    inline void mins(int&a,int b){if(a>b)a=b;}
    inline void maxs(int&a,int b){if(a<b)a=b;}
    long long ans=0;
    int t[100005],v[100005],id[100005];
    int vs[20][100005],bit[20][100005],dt[20][100005];
    int X,v0;
    void build(int L,int R,int h=0){
        int*x=vs[h];
        if(L<R){
            int M=L+R>>1;
            build(L,M,h+1);
            build(M+1,R,h+1);
            int p1=L,p2=M+1,*p3=x+L,*y=vs[h+1];
            while(p1<=M&&p2<=R)*(p3++)=y[(y[p1]<y[p2]?p1:p2)++];
            while(p1<=M)*(p3++)=y[p1++];
            while(p2<=R)*(p3++)=y[p2++];
        }else x[L]=v[L];
    }
    void s1(int L,int R,int h=0){
        int*x=vs[h];
        if(R<X){
            int p=std::upper_bound(x+L,x+R+1,v0)-(x+L);
            ans-=R+1-L-p;
            for(int*a=bit[h]+L-1;p;p-=p&-p)ans-=a[p];
            ans+=dt[h][L];
            return;
        }
        if(L!=R){
            int M=L+R>>1;
            s1(L,M,h+1);
            if(X-1>M)s1(M+1,R,h+1);
        }
    }
    void s2(int L,int R,int h=0){
        int*x=vs[h];
        if(X<L){
            int p=std::lower_bound(x+L,x+R+1,v0)-(x+L);
            ans-=p;
            for(int*a=bit[h]+L-1;p;p-=p&-p)ans+=a[p];
            return;
        }
        if(L!=R){
            int M=L+R>>1;
            if(X<M)s2(L,M,h+1);
            s2(M+1,R,h+1);
        }
    }
    void del(int L,int R,int h=0){
        int*x=vs[h];
        ++dt[h][L];
        int p=std::lower_bound(x+L,x+R+1,v0)-(x+L)+1;
        for(int*a=bit[h]+L-1,N=R-L+1;p<=N;p+=p&-p)++a[p];
        if(L!=R){
            int M=L+R>>1;
            if(X<=M)del(L,M,h+1);
            else del(M+1,R,h+1);
        }
    }
    int n,m;
    int main(){
        n=read();m=read();
        for(int i=1,a;i<=n;i++){
            v[i]=a=read();
            id[a]=i;
            ans+=i-1;
            for(int w=a;w;w-=w&-w)ans-=t[w];
            while(a<=n)++t[a],a+=a&-a;
        }
        build(1,n);
        for(int i=1;i<=m;i++){
            printf("%lld
    ",ans);
            v0=read();
            X=id[v0];
            s1(1,n);
            s2(1,n);
            del(1,n);
        }
        return 0;
    }
  • 相关阅读:
    小数据池以及深浅拷贝
    字典的初识,了解
    元组:认识,索引 切片
    列表的认识,嵌套,增删改查
    bool、字符串方法、for循环
    字符串格式化输出、while循环、运算符.
    Python的基础知识与历史应用
    git错误:error: failed to push some refs to 'https://...'
    golang中gin框架使用logrus
    golang中如何监控多个goroute协程是否执行完成
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5347766.html
Copyright © 2011-2022 走看看