zoukankan      html  css  js  c++  java
  • BZOJ3196(TYVJ1730)二逼平衡树

    传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3196

                http://www.tyvj.cn/Problem_Show.aspx?id=1730

    3196: Tyvj 1730 二逼平衡树

    Time Limit: 10 Sec  Memory Limit: 128 MB

    Description

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
    1.查询k在区间内的排名
    2.查询区间内排名为k的值
    3.修改某一位值上的数值
    4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
    5.查询k在区间内的后继(后继定义为大于x,且最小的数)

    Input

    第一行两个数 n,m 表示长度为n的有序序列和m个操作
    第二行有n个数,表示有序序列
    下面有m行,opt表示操作标号
    若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
    若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
    若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
    若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
    若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

    Output

    对于操作1,2,4,5各输出一行,表示查询结果

    Sample Input

    9 6
    4 2 2 1 9 4 0 1 1
    2 1 4 3
    3 4 10
    2 1 4 3
    1 2 5 9
    4 3 9 5
    5 2 8 5

    Sample Output

    2
    4
    3
    4
    9

    HINT

    1.n和m的数据范围:n,m<=50000

    2.序列中每个数的数据范围:[0,1e8]

    3.虽然原题没有,但事实上5操作的k可能为负数
    WRNM....这题我改了一上午。。题目挺水的。。但是要注意细节。。最大的细节就是k不在树里你怎么判断他的排名。。一定要模拟清楚了。。。
    还要平衡树删除叶子节点的。。也要想清楚怎么删。。
     
    Codes:
    #include<set>
    #include<queue>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N = 50010;
    const int inf = 2147483647;
    #define Ch1 (i<<1)
    #define Ch2 (Ch1|1)
    #define L(i) (tre[i].s[0])
    #define R(i) (tre[i].s[1])
    #define For(i,n) for(int i=1;i<=n;i++)
    #define Rep(i,l,r) for(int i=l;i<=r;i++)
    
    struct tnode{
        int l,r,mid;
        int rt;
    }T[N<<2];
    
    struct treap{
        int s[2],v,size,pri,p;
        void Sets(int x,int y,int z){
            size = 1; v = x; pri = y;p = z;
        }
    }tre[N<<5];
    int n,m,l,r,k,A[N],op,tot;
    
    void Update(int i){
        tre[i].size = tre[L(i)].size + tre[R(i)].size + 1;
    }
    
    void Rot(int &y,int f){
        int x = tre[y].s[!f];
        tre[y].s[!f] = tre[x].s[f];
        tre[x].s[f] = y;
        Update(y);Update(x);
        y = x;
    }
    
    void Insert(int &i,int v,int p){
        if(!i){
            tre[i=++tot].Sets(v,rand(),p);
            return;
        }
        int f = v > tre[i].v;
        Insert(tre[i].s[f],v,i);
        if(tre[tre[i].s[f]].pri > tre[i].pri) Rot(i,!f);
        else                                  Update(i);
    }
    
    void Del(int &i,int v){
        if(tre[i].v==v){
            if(!L(i)||!R(i)){
                if((!L(i))&&(!R(i))){
                    tre[i].size = 0;
                    i = 0;return;
                }
                if(!tre[i].s[0]) i = tre[i].s[1];
                else             i = tre[i].s[0];
            }
            else{
                int f = tre[L(i)].pri > tre[R(i)].pri;
                Rot(i,f);
                Del(tre[i].s[f],v);
            }
        }else Del(tre[i].s[v>tre[i].v],v);
        Update(i);
    }
    
    void Build(int l,int r,int i){
        T[i].l = l ;T[i].r = r;T[i].mid = (l+r)>>1;
        Rep(j,l,r) Insert(T[i].rt,A[j],T[i].rt);
        if(l==r) return;
        Build(l,T[i].mid,Ch1); Build(T[i].mid+1,r,Ch2);
    }
    
    void read(int &v){
        char ch = getchar(); int num = 0 , q = 1;
        while(ch>'9'||ch<'0'){
            if(ch=='-') q = -1;
            ch = getchar();
        }
        while(ch>='0'&&ch<='9'){
            num = num * 10 + ch - '0';
            ch = getchar();
        }
        v = num * q;
    }
    
    int ranks(int i,int v){
        if(!i) return 0;
        if(tre[i].v >= v) return ranks(L(i),v);
        else              return tre[L(i)].size + 1 + ranks(R(i),v);
    }
    
    int prev(int i,int v){
        if(!i) return -inf;
        if(tre[i].v < v) return max(tre[i].v,prev(R(i),v));
        else             return prev(L(i),v);
    }
    
    int succ(int i,int v){
        if(!i) return inf;
        if(tre[i].v> v) return min(tre[i].v,succ(L(i),v));
        else            return succ(R(i),v);
    }
    
    int query(int i,int l,int r,int v){
        if(l<=T[i].l&&T[i].r<=r){
            if(op==1||op==2) return ranks(T[i].rt,v);
            if(op==4)        return prev(T[i].rt,v);
            if(op==5)        return succ(T[i].rt,v);
        }
        if(r<=T[i].mid) return query(Ch1,l,r,v);else
        if(l>T[i].mid)  return query(Ch2,l,r,v);else{
            if(op==1||op==2) return query(Ch1,l,T[i].mid,v) + query(Ch2,T[i].mid+1,r,v);
            if(op==4)        return max(query(Ch1,l,T[i].mid,v),query(Ch2,T[i].mid+1,r,v));
            if(op==5)        return min(query(Ch1,l,T[i].mid,v),query(Ch2,T[i].mid+1,r,v));
        }
    }
    
    void Modify(int i,int x,int delta){
        Del(T[i].rt,A[x]);
        Insert(T[i].rt,delta,i);
        if(T[i].l==T[i].r) {
            A[x] = delta;
            return;
        }
        if(x<=T[i].mid) Modify(Ch1,x,delta);
        else            Modify(Ch2,x,delta);
    }
    
    int main(){
        #ifndef ONLINE_JUDGE
            freopen("sb.in","r",stdin);
            freopen("sb.out","w",stdout);
        #endif
        //srand(time(NULL));
        read(n);read(m);
        For(i,n) read(A[i]);
        Build(1,n,1);
        For(i,m){
            read(op);
            if(op==3){read(l);read(r);Modify(1,l,r);continue;};
            read(l);read(r);read(k);
            if(op==1) printf("%d
    ",query(1,l,r,k)+1);
            if(op==2){
                int Left = 0 , Right = inf;
                while(Right - Left > 1){
                    int Mid = (Left + Right) >> 1;
                    if(query(1,l,r,Mid) >= k) Right = Mid;
                    else                      Left  = Mid;
                }
                if(query(1,l,r,Right)+1==k) printf("%d
    ",Right);
                else                        printf("%d
    ",Left);
            }
            if(op==4) printf("%d
    ",query(1,l,r,k));
            if(op==5) printf("%d
    ",query(1,l,r,k));
        }
        return 0;
    }
  • 相关阅读:
    P3_C17:设计对象的原则
    【c++编程习惯】关于我自己
    淘宝退货业务 活动图
    UML绘图要点
    P2_C4-7:初始阶段
    P3_C8-11:细化阶段-基础迭代
    P3_C14-16:面向对象设计
    P3_C12-13:逻辑架构和包图
    P1_C1-3:系统分析与设计概要
    Chapter11 线程
  • 原文地址:https://www.cnblogs.com/zjdx1998/p/3893440.html
Copyright © 2011-2022 走看看