AmazingCounters.com

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\n",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\n",Right);
            else                        printf("%d\n",Left);
        }
        if(op==4) printf("%d\n",query(1,l,r,k));
        if(op==5) printf("%d\n",query(1,l,r,k));
    }
    return 0;
}

 

 

posted @ 2014-08-05 23:18  ZJDx1998  阅读(186)  评论(0编辑  收藏  举报