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);
        }
    }
}
原文地址:https://www.cnblogs.com/qscqesze/p/5000499.html