BZOJ3295: [Cqoi2011]动态逆序对

Description

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

Input

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

Output

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

Sample Input

5 4
1
5
3
4
2
5
1
4
2

Sample Output

5
2
2
1

样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

HINT

 

N<=100000 M<=50000

 
随便写好了。。。
写个树状数组套平衡树,光荣踩时过
#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
    if(head==tail) {
        int l=fread(buffer,1,BufferSize,stdin);
        tail=(head=buffer)+l;
    }
    return *head++;
}
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=100010;
const int maxnode=4000010;
struct Node {
    Node* ch[2];
    int r,s,v,del;
    void maintain() {s=ch[0]->s+ch[1]->s+(!del);}
}nodes[maxnode],*null=&nodes[0];
int ToT;
Node* newnode(int v) {
    Node* o=&nodes[++ToT];o->ch[0]=o->ch[1]=null;
    o->del=0;o->s=1;o->v=v;return o;
}
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 v) {
    if(o==null) o=newnode(v);
    else {
        int d=v>o->v;insert(o->ch[d],v);
        if(o->ch[d]->r>o->r) rotate(o,d^1);
        else o->maintain();
    }
}
int query(Node* &o,int v) {
    if(o==null) return 0;
    if(v<=o->v) return query(o->ch[0],v);
    return query(o->ch[1],v)+o->ch[0]->s+(!o->del);
}
void remove(Node* &o,int v) {
    if(v==o->v) o->del=1;
    else remove(o->ch[v>o->v],v);
    o->maintain();
}
void print(Node* &o) {
    if(o==null) return;
    print(o->ch[0]);
    if(!o->del) printf("%d ",o->v);
    print(o->ch[1]);
}
int n,m,A[maxn],pos[maxn],c[maxn];
struct Tree {
    Node* root[maxn];
    void add(int x,int v) {
        for(;x<=n;x+=x&-x) insert(root[x],v);
    }
    int sum(int x,int v) {
        int res=0;
        for(;x;x-=x&-x) res+=query(root[x],v);
        return res;
    }
    void del(int x,int v) {
        for(;x<=n;x+=x&-x) remove(root[x],v);
    }
}T1,T2;
void add(int x) {
    for(;x<=n;x+=x&-x) c[x]++;
}
int query(int x) {
    int sum=0;
    for(;x;x-=x&-x) sum+=c[x];
    return sum;
}
long long ans;
int main() {
    n=read();m=read();
    rep(i,1,n) {
        add(n-(A[i]=read())+1);ans+=query(n-A[i]);
        T1.root[i]=T2.root[i]=null;pos[A[i]]=i;
    }
    rep(i,1,n) T1.add(i,n-A[i]+1),T2.add(n-i+1,A[i]);
    printf("%lld\n",ans);
    while(--m) {
        int x=pos[read()];
        ans-=T1.sum(x-1,n-A[x]+1)+T2.sum(n-x,A[x]);
        T1.del(x,n-A[x]+1);T2.del(n-x+1,A[x]);
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2015-12-01 17:26  wzj_is_a_juruo  阅读(187)  评论(0编辑  收藏  举报