• 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
    ",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
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Spring Could与Dubbo、Docker、K8S
    Spring Could 问题
    再看Spring Could微服务的关键组件
    2018第46周日
    好用的天猫精灵
    好用的微软桌面
    PostgreSQL性能极限
    微服务常见问题及解决方案
    最近看到的几本书
    程序员如何修炼管理思维
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5010739.html
Copyright © 2020-2023  润新知