• HDU 5412——CRB and Queries——————【线段树套Treap(并没有AC)】


    CRB and Queries

    Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
    Total Submission(s): 1602    Accepted Submission(s): 409


    Problem Description
    There are N boys in CodeLand.
    Boy i has his coding skill Ai.
    CRB wants to know who has the suitable coding skill.
    So you should treat the following two types of queries.
    Query 1: 1 l v
    The coding skill of Boy l has changed to v.
    Query 2: 2 l r k
    This is a report query which asks the k-th smallest value of coding skill between Boy l and Boy r(both inclusive).
     
    Input
    There are multiple test cases. 
    The first line contains a single integer N.
    Next line contains N space separated integers A1A2, …, AN, where Ai denotes initial coding skill of Boy i.
    Next line contains a single integer Q representing the number of queries.
    Next Q lines contain queries which can be any of the two types.
    1 ≤ NQ ≤ 105
    1 ≤ Aiv ≤ 109
    1 ≤ l ≤ r ≤ N
    1 ≤ k ≤ r  l + 1

     
    Output
    For each query of type 2, output a single integer corresponding to the answer in a single line.
     
    Sample Input
    5
    1 2 3 4 5
    3
    2 2 4 2
    1 3 6
    2 2 4 2
     
    Sample Output
    3
    4
     
    Author
    KUT(DPRK)
     
    Source
     

    题目大意:给你一个数列有n个数,q次询问。询问1可以把某个位置改为值b。询问2然后问L - R之间第k大的数是多少。简单来说,就是带修改的动态区间第k大问题。

    解题思路:用线段树维护Ci在去重后的所有可能出现在数列中的数当中的大小排名,用Treap维护Ci在数列中的位置关系。其实我觉得这才是内涵。然后对于查询区间L - R的第k大。那么如果在线段树左儿子代表的Treap树中在R位置之前的个数减去左儿子代表的Treap树中的(L-1)之前的个数大于k,那么就可以在左儿子中找位置。

    #include<stdio.h>
    #include<string.h>
    #include<time.h>
    #include<algorithm>
    using namespace std;
    #define mid (L+R)/2
    #define lson rt*2,L,mid
    #define rson rt*2+1,mid+1,R
    const int maxn=1e6;
    struct Treap{
        int rk;
        int coun;
        int sz;
        int v;
        Treap *ch[2];
        Treap() {
            coun=0;
            sz=0;
            rk=-maxn;   //
            v=0;
        }
        int cmp(int x) const {
            if(x==v){
                return -1;
            }
            return x<v ? 0:1;
        }
    };
    Treap *seg[maxn*8];
    Treap *null;
    int oper[maxn][4];
    int a[maxn],b[maxn*3];
    int discr(int l,int r,int key){
        while(l<=r){
            int md=(l+r)/2;
            if(key<b[md]){
                r=md-1;
            }else if(key > b[md]){
                l=md+1;
            }else{
                return md;
            }
        }
        return -1;
    }
    void update(Treap * &o){
        o->sz = o->ch[0]->sz + o->coun + o->ch[1]->sz;
    }
    void rotate(Treap * &o,int d){
        Treap *k=o->ch[d^1]; o->ch[d^1]= k->ch[d]; k->ch[d]=o;
        update(o); update(k);  o=k;
    }
    void insert_tp(Treap * &o,int x){
        if(o==null){
            o = new Treap();
            o->ch[0]=o->ch[1]=null;
            o->v = x; o->coun = 1; o->rk = rand();
        }else{
            int d=o->cmp(x);
            insert_tp(o->ch[d],x);
            if(o->ch[d]->rk > o->rk) rotate(o,d^1);
        }
        update(o);
    }
    void insert_seg(int rt,int L,int R,int pos,int x){
        insert_tp(seg[rt],x);
        if(L==R)
            return ;
        if(pos<=mid){
            insert_seg(lson,pos,x);
        }else{
            insert_seg(rson,pos,x);
        }
    }
    void free_tp(Treap *&o){
        if(o->ch[0]==null&&o->ch[1]==null){
            free(o);
            return ;
        }
        if(o->ch[0]!=null){
            free_tp(o->ch[0]);
        }
        if(o->ch[1]!=null){
            free_tp(o->ch[1]);
        }
        free(o);
    }
    void clean(int rt,int L,int R){
        if(L==R){
            free_tp(seg[rt]);
            return ;
        }
        clean(lson);
        clean(rson);
        free_tp(seg[rt]);
    }
    void del_tp(Treap * &o,int x){
        int d=o->cmp(x);
        if(d==-1){
            if(o->ch[0]==null&&o->ch[1]==null){     //
                Treap *pt=o;
                o = null;
                free(pt);
            }
            else if(o->ch[0]==null){
                Treap *pt=o;
                o=o->ch[1];
                free(pt);
            }else if(o->ch[1]==null){
                Treap *pt=o;
                o= o->ch[0];
                free(pt);
            }else{
                int d2=( o->ch[0]->rk >o->ch[1]->rk ? 1:0 );
                rotate(o,d2);
                del_tp(o->ch[d2],x);
            }
        }else{
            del_tp(o->ch[d],x);
        }
        update(o);
    }
    void del_seg(int rt,int L,int R,int pos,int x){
        del_tp(seg[rt],x);
        if(L==R)
            return ;
        if(pos<=mid){
            del_seg(lson,pos,x);
        }else{
            del_seg(rson,pos,x);
        }
    }
    int select(Treap *o,int x){
        if(o==null){
            return 0;
        }
        if(o->v > x) return select(o->ch[0],x);
        return o->ch[0]->sz + o->coun +select(o->ch[1],x);
    }
    int query(int rt,int L,int R,int x,int y,int k){
        if(L==R) return L;
        int ans=select(seg[rt*2],y)-select(seg[rt*2],x);
        if(ans>=k)
            return query(lson,x,y,k);
        else return query(rson,x,y,k-ans);
    }
    void init(){
        null =new Treap();
        null->ch[0]=null->ch[1]=null;
        null->sz = null->coun=0;
        for(int i=0;i<=maxn*4-1;i++){
            seg[i] = null;
        }
    }
    int main(){
    //    freopen("1007.in","r",stdin);
    //    freopen("OUT.txt","w",stdout);
        int n,Q,typ,x,y,z,nn,mm;
        while(scanf("%d",&n)!=EOF){
            init();
            mm=0;
            for(int i=0;i<n;i++){
                scanf("%d",&a[i]);
                b[mm++]=a[i];
            }
            scanf("%d",&Q);
            for(int i=0;i<Q;i++){
                scanf("%d",&typ);
                oper[i][0]=typ;
                if(typ==2){
                    scanf("%d%d%d",&x,&y,&z);
                    oper[i][1]=x;
                    oper[i][2]=y;
                    oper[i][3]=z;
                }else{
                    scanf("%d%d",&x,&z);
                    oper[i][1]=x;
                    oper[i][2]=z;
                    b[mm++]=z;
                }
            }
            sort(b,b+mm);
            nn=1;
            for(int i=1;i<mm;i++){
                if(b[i]!=b[i-1]){
                    b[nn++]=b[i];
                }
            }
            for(int i=0;i<n;i++){
                a[i]= discr(0,nn-1,a[i])+1;
                insert_seg(1,1,nn,a[i],i+1);
            }
            for(int i=0;i<Q;i++){
                if(oper[i][0]==1){
                    int kk=0;
                    del_seg(1,1,nn,a[oper[i][1]-1],oper[i][1]);
                    kk=discr(0,nn-1,oper[i][2]);
                    a[oper[i][1]-1]=kk+1;
                    insert_seg(1,1,nn,a[oper[i][1]-1],oper[i][1]);
                }else{
                    int tmp=query(1,1,nn,oper[i][1]-1,oper[i][2],oper[i][3])-1;
                    printf("%d
    ",b[tmp]);
                }
            }
            clean(1,1,nn);
        }
        return 0;
    }
    
    
    
    /*
    
    
    5
    1 1 1 1 1
    10
    1 2 3
    2 1 4 3
    1 5 6
    1 4 2
    1 5 3
    2 1 3 3
    2 1 4 4
    2 2 5 2
    2 2 5 3
    2 2 5 4
    
    
    
    */
    

      

  • 相关阅读:
    转载:KOF97东丈
    写一个ajax程序就是如此简单
    转载:97特瑞心得
    老生常谈:享元模式
    获得微软最有影响力开发者
    老生常谈设计模式系列文章索引
    asp.net中的异步页面
    转载:KOF97简易出招原理解析
    leaks 使用手册
    ObjectiveC中一种消息处理方法performSelector: withObject:
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4801690.html
Copyright © 2020-2023  润新知