uva11990 动态逆序对

这题说的是给了一个数组,按照他给的顺序依次删除数,在删除之前输出此时的逆序对个数

我们用Fenwick树 维护这整个数列, C[i]是一个 treap的头, 管理了在树状数组中 能影响他的点,然后我们用名次树去计算 在C[i]下小于等于要删除的那个数的个数就ok了。

#include <iostream>
#include <algorithm>
#include <string.h>
#include <vector>
#include <cstdio>
#include <stdlib.h>
using namespace std;
const int maxn=200005;
struct Node
{
    Node *ch[2];
    int r;
    int s;
    int v;
    int vloc;
    int cmp(int x)const
    {
        if(x==v)return -1;
        return x<v?0:1;
    }
    void maintain()
    {
        s=ch[0]->s+ch[1]->s+vloc;
    }
};
Node *null=new Node();
void rotate(Node *&o, int d)
{
    Node *k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
    o->maintain();k->maintain(); o=k;
}
void insert(Node *&o,int x)
{
    if(o==null){
        o=new Node();
        o->ch[0]=o->ch[1]=null; o->v=x; o->r=rand();o->vloc=1;o->s=1;
    }else{
       int d=o->cmp(x);
       if(d==-1){
         o->vloc+=1;
       }else{
         insert(o->ch[d],x);if( o->ch[d]->r > o->r) rotate(o,d^1);
       }
    }
    o->maintain();
}
void remove(Node *&o, int x)
{
    int d=o->cmp(x);
    if(d==-1){
        if(o->vloc > 1){
             o->vloc-=1;
        }else if(o->ch[0]==null)o=o->ch[1];
        else if(o->ch[1]==null) o=o->ch[0];
        else{
            int d2 = o->ch[0]->r > o->ch[1]->r ? 1 : 0 ;
            rotate(o,d2); remove(o->ch[d2],x);
        }
    }else remove(o->ch[d],x);
    if(o!=null)
    o->maintain();
}
int find(Node *o,int x)
{
    int num=0;
    while(o!=null)
    {
        int d=o->cmp(x);
        if(d==-1){
            num += o->ch[0]->s + o->vloc ;
            break;
        }else if(d==1){
            num+=o->ch[0]->s+o->vloc;
            o=o->ch[1];
        }else{
            o=o->ch[0];
        }
    }
    return num;
}
Node *C[maxn];
int cc[maxn],A[maxn];
int lowbit(int x)
{
    return (-x)&x;
}
void init(int n)
{
    for(int i=0; i<=n; i++)
        C[i]=null,cc[i]=0;
}
int N,M;
void add1(int x, int v)
{
    while(x<=N){
        cc[x]+=v;
        x+=lowbit(x);
    }
}
int sum1(int x){
    int ans=0;
    while(x>0){
        ans+=cc[x];
        x-=lowbit(x);
    }
    return ans;
}
void delet(int x,int v)
{
      while(x<=N)
      {
          remove(C[x],v);
          x+=lowbit(x);
      }
}
int summ(int x,int v)
{
    int ans=0;
     while(x>0)
    {
       ans+=find(C[x],v);
       x-=lowbit(x);
    }
    return ans;
}
int main()
{
    null->s=0;

    while(scanf("%d%d",&N,&M)==2)
    {
       init(N);
       long long ans=0;
       for(int i=1; i<=N; i++)
        {
            int d;
            scanf("%d",&d);
            A[d]=i;
            ans+=sum1(N)-sum1(d);
            add1(d,1);
            int loc=i;
            while(loc<=N)
            {
                insert(C[loc],d); loc+=lowbit(loc);
            }
       }
       for(int i=1; i<=M; i++)
        {
            int d;
            printf("%lld
",ans);
            scanf("%d",&d);
            int s1xiaoyu=summ(A[d],d);
            int ss1=sum1(A[d]);
            ans-=(ss1-s1xiaoyu);
            int s2xiaoyu=summ(N,d);
            ans-=s2xiaoyu-s1xiaoyu;
            add1(A[d],-1);
            delet(A[d],d);
        }
    }
    return 0;
}
/*
5 4
1
5
3
4
2
5
1
4
2
*/
View Code
原文地址:https://www.cnblogs.com/Opaser/p/4906530.html