zoukankan      html  css  js  c++  java
  • UVA 11990 ``Dynamic'' Inversion 动态逆序对

    ``Dynamic'' Inversion

    Time Limit: 20 Sec

    Memory Limit: 256 MB

    题目连接

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3141

    Description

    You are given a permutation f1,2,3,. . . ,ng. Remove m of them one by one, and output the number of
    inversion pairs before each removal. The number of inversion pairs of an array A is the number of
    ordered pairs (i; j) such that i < j and A[i] > A[j].

    Input

    The input contains several test cases. The rst line of each case contains two integers n and m
    (1  n  200;000, 1  m  100;000). After that, n lines follow, representing the initial permutation.
    Then m lines follow, representing the removed integers, in the order of the removals. No integer will
    be removed twice. The input is terminated by end-of- le (EOF).

    Output

    For each removal, output the number of inversion pairs before it.
    Explanation: (1,5,3,4,2)->(1,3,4,2)->(3,4,2)->(3,2)->(3)

    Sample Input

    5 4
    1
    5
    3
    4
    2
    5
    1
    4
    2

    Sample Output

    5
    2
    2
    1

    HINT

    题意

    给你n个数,然后有m次操作,每次操作可以删除一个数

    然后问你每次删除之前,还有多少个逆序对

    题解:

    对于每个数关于逆序对的贡献,就是

    这个数前面有多少个数比他大,后面有多少个数比他小

    这就是贡献~

    然后我们就树状数组套treap来维护这些信息就好了

    线段树会TLE。。。

    代码:

    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<cstring>
    #include<ctime>
    using namespace std;
    inline long long read()
    {
        long long x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    #define maxn 12200005
    long long tmp = 0;
    int a[maxn];
    int pos[maxn];
    int n,m;
    ////////////////treap
    struct Treap
    {
        int root[maxn],sz,s[maxn],ls[maxn],rs[maxn],v[maxn],w[maxn],rnd[maxn];
        void init()
        {
            memset(root,0,sizeof(root));
            sz=0;
        }
        void Updata(int k)
        {
            s[k]=s[ls[k]]+s[rs[k]]+w[k];
        }
        void Rturn(int &k)
        {
            int t;
            t=ls[k],ls[k]=rs[t],rs[t]=k,s[t]=s[k];
            Updata(k);k=t;
        }
        void Lturn(int &k)
        {
            int t;
            t=rs[k],rs[k]=ls[t],ls[t]=k,s[t]=s[k];
            Updata(k);k=t;
        }
        void Insert(int &k,int num)
        {
            if(!k)
            {
                k=++sz;s[k]=w[k]=1;ls[k]=rs[k]=0;rnd[k]=rand();
                v[k]=num;return;
            }
            s[k]++;
            if(v[k]==num)w[k]++;
            else if(num<v[k])
            {
                Insert(ls[k],num);
                if(rnd[ls[k]]<rnd[k])
                    Rturn(k);
            }
            else
            {
                Insert(rs[k],num);
                if(rnd[rs[k]]<rnd[k])
                    Lturn(k);
            }
        }
        void Del(int &k,int num)
        {
            if(v[k]==num)
            {
                if(w[k]>1){
                    w[k]--;
                    s[k]--;
                    return;
                }
                if(ls[k]*rs[k]==0)
                    k=ls[k]+rs[k];
                else if(rnd[ls[k]]<rnd[rs[k]])
                    Rturn(k),Del(k,num);
                else
                    Lturn(k),Del(k,num);
            }
            else if(num<v[k]){
                Del(ls[k],num);
                s[k]--;
            }
            else{
                Del(rs[k],num);
                s[k]--;
            }
        }
        void Find(int k,int num)
        {
            if(!k)return;
            if(v[k]<=num){
                tmp+=s[ls[k]]+w[k];
                Find(rs[k],num);
            }
            else Find(ls[k],num);
        }
    }Tr;
    
    /////////////////////
    
    /////////////////////线段树
    int lowbit(int x)
    {
        return x&(-x);
    }
    void Bit_updata(int x,int v)
    {
        for(;x<=n+10;x+=lowbit(x))
            Tr.Insert(Tr.root[x],v);
    }
    void Bit_change(int x,int v)
    {
        for(;x<=n+10;x+=lowbit(x))
            Tr.Del(Tr.root[x],v);
    }
    void Bit_query(int x,int num)
    {
        for(;x;x-=lowbit(x))
            Tr.Find(Tr.root[x],num);
    }
    ///////////////////////////
    
    ///////////////////////////树状数组
    struct Bit
    {
    
        int a[400005];
        int lowbit(int x)
        {
            return x&(-x);
        }
        int query(int x)
        {
            int ans = 0;
            for(;x;x-=lowbit(x))
                ans+=a[x];
            return ans;
        }
        void updata(int x,int v)
        {
            for(;x<400005;x+=lowbit(x))
                a[x]+=v;
        }
    }bit,bit2;
    
    ///////////////////////////
    
    
    int main()
    {
        //freopen("a+b.in","r",stdin);
        srand(time(NULL));
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(bit2.a,0,sizeof(bit2.a));
            Tr.init();
            memset(bit.a,0,sizeof(bit.a));
            long long Res = 0;
            for(int i=1;i<=n;i++)
            {
                a[i]=read();
                Bit_updata(i,a[i]);
                bit.updata(a[i],1);
                Res += (i-bit.query(a[i]-1)-1);
                pos[a[i]]=i;
            }
            memset(bit.a,0,sizeof(bit.a));
            for(int i=1;i<=n;i++)
                bit.updata(i,1),bit2.updata(i,1);
            for(int i=1;i<=m;i++)
            {
                printf("%lld
    ",Res);
                int x;scanf("%d",&x);
                long long ans1 = bit2.query(x)-1;//总共有多少数比他小
                Bit_query(pos[x],x);long long ans2 = tmp;tmp=0;ans2--;//在他前面有多少比他小
                long long ans3 = bit.query(pos[x])-1;//在他前面一共有多少个数
                long long Ans1 = ans3 - ans2;//前面有多少个数比他大
                long long Ans2 = ans1 - ans2;//后面有多少个数比他小
                //cout<<ans1<<" "<<ans2<<" "<<ans3<<endl;
                //cout<<Ans1<<" "<<Ans2<<endl;
                Res = Res-Ans1-Ans2;
                Bit_change(pos[x],x);
                bit2.updata(x,-1);
                bit.updata(pos[x],-1);
            }
        }
    }
  • 相关阅读:
    知识点:synchronized 原理分析
    知识点:spring 完全手册
    知识点:图说 Mysql 权限管理
    知识点:Mysql 基本用法之流程控制
    知识点:Mysql 基本用法之函数
    知识点:Mysql 基本用法之存储过程
    知识点:Mysql 基本用法之事务
    知识点:Mysql 基本用法之触发器
    知识点:Mysql 基本用法之视图
    知识点:MySQL表名不区分大小写的设置方法
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5000499.html
Copyright © 2011-2022 走看看