zoukankan      html  css  js  c++  java
  • BZOJ 2141 排队 线段树套替罪羊

    Description

    排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量。幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。

    Input

    第一行为一个正整数n,表示小朋友的数量;第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;第三行为一个正整数m,表示交换操作的次数;以下m行每行包含两个正整数ai和bi¬,表示交换位置ai与位置bi的小朋友。

    Output

    输出文件共m行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度。

    Sample Input

    【样例输入】
    3
    130 150 140
    2
    2 3
    1 3

    Sample Output

    1
    0
    3
    【样例说明】
    未进行任何操作时,(2,3)满足条件;
    操作1结束后,序列为130 140 150,不存在满足ihj的(i,j)对;
    操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。
    【数据规模和约定】
    对于100%的数据,1≤m≤2*103,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。
    数据结构的嵌套。外层位置线段树内层权值平衡树(替罪羊)然后考虑l,r删除或增加对答案的贡献,所以搞两个rank函数再xjb一搞就好了

    #include <cstring>
    #include <iostream>
    #include <stdio.h>
    #include <vector>
    using namespace std;
    const double alpha = 0.755;
    const int MAXN = 20005;
    int n,h[MAXN],len,m;
    long long Ans;
    
    
    template<typename _t>
    inline _t read(){
        _t x = 0;
        int f = 1;
        char ch = getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-f;
        for(;ch>='0'&&ch<='9';ch=getchar())x=(x*10)+(ch^48);
        return (_t)x*f;
    }
    
    struct node{
        int s,cover,v,ex;
        node *ch[2];
        
        void operator delete (void *p);
    
        void* operator new (size_t);
    
        bool bad(){
            return ch[0]->cover > cover * alpha || ch[1]->cover > cover * alpha;
        }
    
        void Maintain(){
            s = ch[0]->s+ch[1]->s+ex;
            cover =ch[0]->cover+ch[1]->cover+1;
        }
    
        node(){
            s=v=cover=ex=0;
            ch[0]=ch[1]=NULL;
        }
    
        node(int x);
        
    }*null = new node(),*lst[MAXN<<5],*C,*mempool;
    
    vector<node*>q;
    
    void* node :: operator new (size_t){
        node * p;
        if(!q.empty()){
            p = q.back();
            q.pop_back();
        }
        else{
            if(C==mempool){
                C = new node[1<<15];
                mempool = C + (1<<15);
            }
            p = C++;
        }
        return p;
    }
    
    void node :: operator delete (void *p){
        q.push_back((node*)p);
    }
    
    node :: node(int x){
        v=x;s=cover=ex=1;
        ch[0]=ch[1]=null;
    }
    
    void travel(node *p){
        if(p == null)return;
        travel(p->ch[0]);
        if(p->ex)lst[++len] = p;
        else delete p;
        travel(p->ch[1]);
    }
    
    node *divide(int l,int r){
        if(l>r)return null;
        int m = l + r >> 1;
        lst[m]->ch[0]=divide(l,m-1);
        lst[m]->ch[1]=divide(m+1,r);
        lst[m]->Maintain();
        return lst[m];
    }
    
    void rebuild(node *&o){
        len = 0;
        travel(o);
        o=divide(1,len);
    }
    
    inline int rank_min(node *o,int x){
        int Ans = 0;
        while(o!=null){
            if(x<=o->v)o = o -> ch[0];
            else Ans += o->ch[0]->s+o->ex,o = o->ch[1];
        }
        return Ans;
    }
    
    inline int rank_max(node *o,int x){
        int Ans = 0;
        while(o!=null){
            if(x>=o->v)o = o->ch[1];
            else Ans += o->ch[1]->s+o->ex,o=o->ch[0];
        }
        return Ans;
    }
    
    node **insert(node *&o,int x){
        if(o == null){
            o = new node(x);
            return &null;
        }
        node **p = insert(o->ch[o->v<=x],x);
        if(o->bad())p = &o;
        o->Maintain();
        return p;
    }
    
    void Insert(node *&o,int x){
        node **p = insert(o,x);
        if(*p!=null)rebuild(*p);
    }
    
    void erase(node *o,int k){
        if(o->ex && k == o->ch[0]->s +1){
            o -> ex=0;
            o-> Maintain();
            return;
        }
        if(o->ch[0]->s>=k)erase(o->ch[0],k);
        else erase(o->ch[1],k-o->ch[0]->s-o->ex);
        o -> Maintain();
    }
    
    void Erase(node *&o,int x){
        erase(o,rank_min(o,x)+1);
        if(o->s < o->cover *alpha)rebuild(o);
    }
    
    struct Tree{
        int l,r,m;
        Tree *ls,*rs;
        node *root;
        void *operator new (size_t);
        Tree(){
            ls=rs=NULL;
            root=null;
            m = l = r =0;
        }
    }*QAQ,*S,*T;
    
    void* Tree :: operator new (size_t){
        if(S==T){
            S = new Tree[1<<15];
            T = S + (1<<15);
        }
        return S++;
    }
    
    void build(Tree *&o,int l,int r){
        if(!o)o=new Tree;
        o->l=l,o->r=r,o->m=l+r>>1;
        for(int i=l;i<=r;i++)Insert(o->root,h[i]);
        if(l==r)return;
        build(o->ls,l,o->m);
        build(o->rs,o->m+1,r);
    }
    
    void Tree_insert(Tree *o,int x,int w){
        Insert(o->root,w);
        if(o->l==o->r)return;
        if(x<=o->m)Tree_insert(o->ls,x,w);
        else Tree_insert(o->rs,x,w);
    }
    
    void Tree_erase(Tree *o,int x,int w){
        Erase(o->root,w);
        if(o->l==o->r)return;
        if(x<=o->m)Tree_erase(o->ls,x,w);
        else Tree_erase(o->rs,x,w);
    }
    
    int Tree_max(Tree *o,int x,int y,int w){
        if(x<=o->l&&o->r<=y)return rank_max(o->root,w);
        int ans = 0;
        if(x<=o->m)ans += Tree_max(o->ls,x,y,w);
        if(o->m<y)ans += Tree_max(o->rs,x,y,w);
        return ans;
    }
    
    int Tree_min(Tree *o,int x,int y,int w){
        if(x<=o->l&&o->r<=y)return rank_min(o->root,w);
        int ans = 0;
        if(x<=o->m)ans += Tree_min(o->ls,x,y,w);
        if(o->m<y)ans += Tree_min(o->rs,x,y,w);
        return ans;
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&h[i]);
        build(QAQ,1,n);
        for(int i=2;i<=n;i++)Ans+=Tree_max(QAQ,1,i-1,h[i]);
        scanf("%d",&m);
        printf("%lld
    ",Ans);
        while(m--){
            int l,r;
            scanf("%d%d",&l,&r);
            if(l!=1)Ans-=Tree_max(QAQ,1,l-1,h[l]);
            if(l!=n)Ans-=Tree_min(QAQ,l+1,n,h[l]);
            Tree_erase(QAQ,l,h[l]);
            if(r!=1)Ans+=Tree_max(QAQ,1,r-1,h[l]);
            if(r!=n)Ans+=Tree_min(QAQ,r+1,n,h[l]);
            Tree_insert(QAQ,r,h[l]);
            if(l!=1)Ans+=Tree_max(QAQ,1,l-1,h[r]);
            if(l!=n)Ans+=Tree_min(QAQ,l+1,n,h[r]);
            Tree_erase(QAQ,r,h[r]);
            if(r!=1)Ans-=Tree_max(QAQ,1,r-1,h[r]);
            if(r!=n)Ans-=Tree_min(QAQ,r+1,n,h[r]);
            Tree_insert(QAQ,l,h[r]);
            swap(h[l],h[r]);
            printf("%lld
    ",Ans);
        }
    }
    




  • 相关阅读:
    Activity(活动)生命周期(1)--返回栈
    探究Activity(1)--Activity的基本用法
    Z-Stack协议栈网络号与信道号的设置
    如何搭建自己的网站到远程服务器(亲测有效)
    新手搭建springmvc+mybits框架的经验分享
    spring+mybits 整合所需jar包的下载路径(亲测有效)
    Map集合的四种常用遍历方式整理
    java设计模式----单例模式
    浅谈H5技术
    jsp内置对象分析
  • 原文地址:https://www.cnblogs.com/Cooook/p/7738530.html
Copyright © 2011-2022 走看看