zoukankan      html  css  js  c++  java
  • P3157 [CQOI2011]动态逆序对

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 
    5 4
    1
    5
    3
    4
    2
    5
    1
    4
    2
    输出样例#1: 
    5
    2
    2
    1
    
    样例解释
    (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

    说明

    N<=100000 M<=50000

    Solution:

      本题带修改主席树板子。

      离散都不需要,直接对每个位置构建主席树,先求出逆序对个数,然后每次删数直接树状数组套主席树改下,考虑该数被删去后对逆序对个数的影响,无非就是排在它前面比它大的数的个数+排在它后面比它小的数的个数(提醒我们还得记录每个数在原序列出现的位置),原逆序对数剪掉这个值就好了。

      (注意:本题卡内存,我们发现每次主席树上的修改只与修改前的那棵主席树有关,而我们查询只需要当前最新的这棵主席树,并不需要返回到更之前的树的情况,所以我们可以回收内存,每次修改直接覆盖掉上棵树的节点就好了。)

    代码:

    /*Code by 520 -- 9.19*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    #define lowbit(x) (x&-x)
    using namespace std;
    const int N=100005;
    int n,m,a[N],rt[N],cnt,pos[N],X[N],Y[N],tx,ty;
    struct node{
        int ls,rs,siz;
    }t[N*120];
    struct bit{
        int c[N];
        il void Clr(){memset(c,0,sizeof(c));}
        il void update(int x,int k){while(x<=n)c[x]+=k,x+=lowbit(x);}
        il int query(int x){int ans=0;while(x)ans+=c[x],x-=lowbit(x);return ans;}
    }b;
    
    int gi(){
        int a=0;char x=getchar();
        while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9') a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return a;
    }
    
    void ins(int l,int r,int k,int x,int lst,int &rt){
        if(!rt)rt=++cnt;t[rt].siz+=x;
        if(l==r) return;
        int m=l+r>>1;
        if(k<=m) ins(l,m,k,x,t[lst].ls,t[rt].ls);
        else ins(m+1,r,k,x,t[lst].rs,t[rt].rs);
    }
    
    il void update(int x,int v){
        int k=a[x];
        while(x<=n) ins(1,n,k,v,rt[x],rt[x]),x+=lowbit(x);
    }
    
    il int querysuc(int x,int y,int v){
        int l=1,r=n,ans=0;tx=0,ty=0;
        for(RE int i=x;i;i-=lowbit(i)) X[++tx]=rt[i];
        for(RE int i=y;i;i-=lowbit(i)) Y[++ty]=rt[i];
        while(l<r){
            int m=l+r>>1;
            if(m>=v){
                For(i,1,tx) X[i]=t[X[i]].ls;
                For(i,1,ty) Y[i]=t[Y[i]].ls;
                r=m;
            }
            else {
                For(i,1,tx) ans-=t[t[X[i]].ls].siz,X[i]=t[X[i]].rs;
                For(i,1,ty) ans+=t[t[Y[i]].ls].siz,Y[i]=t[Y[i]].rs;
                l=m+1;
            }
        }
        return ans;
    }
    
    il int querypre(int x,int y,int v){
        int l=1,r=n,ans=0;tx=0,ty=0;
        for(RE int i=x;i;i-=lowbit(i)) X[++tx]=rt[i];
        for(RE int i=y;i;i-=lowbit(i)) Y[++ty]=rt[i];
        while(l<r){
            int m=l+r>>1;
            if(m<v){
                For(i,1,tx) X[i]=t[X[i]].rs;
                For(i,1,ty) Y[i]=t[Y[i]].rs;
                l=m+1;
            }
            else {
                For(i,1,tx) ans-=t[t[X[i]].rs].siz,X[i]=t[X[i]].ls;
                For(i,1,ty) ans+=t[t[Y[i]].rs].siz,Y[i]=t[Y[i]].ls;
                r=m;
            }
        }
        return ans;
    }
    
    int main(){
        n=gi(),m=gi();b.Clr();
        int x;ll ans=0;
        memset(&t[0],0,sizeof(t[0]));
        For(i,1,n) {
            a[i]=gi(),pos[a[i]]=i,update(i,1);
            ans+=b.query(n)-b.query(a[i]);
            b.update(a[i],1);
        }
        For(i,1,m){
            x=pos[gi()];
            printf("%lld
    ",ans);
            update(x,-1);
            ans-=querysuc(x,n,a[x])+querypre(0,x-1,a[x]);
        }
        return 0;
    }
  • 相关阅读:
    [面试没答上的问题1]http请求,请求头和响应头都有什么信息?
    模拟进度条发现的彩蛋
    实现JavaScript forEach
    JavaScript实现动画效果
    Contents Of My Blogs
    阅读笔记-拍出好照片的30个构图基本功
    阅读笔记-李鸿章传
    阅读笔记-人性的弱点
    阅读笔记-XWord:未来进化
    阅读笔记-活法
  • 原文地址:https://www.cnblogs.com/five20/p/9690082.html
Copyright © 2011-2022 走看看