博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

bzoj 3196: Tyvj 1730 二逼平衡树

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可能为负数
 
 
 
bzoj上A了,tyvj上被卡时,愣是压了好久没压出来……
我写的是区间线段树套treap,听说权值线段树套区间线段树在tyvj上可以卡过去,可惜我不会写回收空间,试了一下还是RE了,还是太弱……
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;

int p,ch,f,ll,rr,mid;
inline int sread(){
    p=0;ch=getchar();f=1;
    while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') p=p*10+ch-48,ch=getchar();
    return p*f;
}
inline int read(){
    p=0;ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') p=p*10+ch-48,ch=getchar();
    return p;
}
struct tree{
    int l,r,k,ra,s,w;
    tree(){
        l=r=0;
    }
}t[1500000];
int root[200000],l[200000],r[200000];
int n,m,num=0,a[50001],w,o;
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
inline void ler(int &p){
    int k=t[p].r;
    t[p].r=t[k].l;
    t[k].l=p;
    t[k].s=t[p].s;
    t[p].s=t[p].w+t[t[p].l].s+t[t[p].r].s;
    p=k;
}
inline void rir(int &p){
    int k=t[p].l;
    t[p].l=t[k].r;
    t[k].r=p;
    t[k].s=t[p].s;
    t[p].s=t[p].w+t[t[p].l].s+t[t[p].r].s;
    p=k;
}
inline void in(int &p,int k){
    if (!p){
        p=++num;
        t[p].k=k;
        t[p].w=t[p].s=1;
        t[p].ra=rand();
        return;
    }
    t[p].s++;
    if (t[p].k==k) t[p].w++;else
    if (t[p].k>k){
        in(t[p].l,k);
        if (t[t[p].l].ra<t[p].ra) rir(p);
    }else{
        in(t[p].r,k);
        if (t[t[p].r].ra<t[p].ra) ler(p);
    }
}
inline int que(int p,int k){
    if (!p) return 0;
    if (t[p].k==k){
        w+=t[p].w;
        return t[t[p].l].s;
    }
    if (t[p].k<k) return t[t[p].l].s+t[p].w+que(t[p].r,k);
    return que(t[p].l,k);
}
inline void build(int p,int ll,int rr){
    for (register int i=ll;i<=rr;i++) in(root[p],a[i]);
    l[p]=ll;r[p]=rr;
    if (ll<rr){
        int mid=(ll+rr)>>1;
        build(p<<1,ll,mid);
        build((p<<1)|1,mid+1,rr);
    }
}
inline int qu(int p,int a,int b,int k){
    if (l[p]==a&&r[p]==b) return que(root[p],k);
    int mid=(l[p]+r[p])>>1;
    if (b<=mid) return qu(p<<1,a,b,k);
    if (a>mid) return qu((p<<1)|1,a,b,k);
    return qu(p<<1,a,mid,k)+qu((p<<1)|1,mid+1,b,k);
}
inline void dell(int &p){
    if (!t[p].l&&!t[p].r) p=0;else
    if (!t[p].l) p=t[p].r;else
    if (!t[p].r) p=t[p].l;else
    if (t[t[p].l].ra<t[t[p].r].ra) rir(p),dell(t[p].r);else ler(p),dell(t[p].l);
}
inline void del(int &p,int k){
    t[p].s--;
    if (t[p].k==k){
        t[p].w--;
        if (t[p].w==0) dell(p);
        return;
    }
    if (t[p].k<k) del(t[p].r,k);else del(t[p].l,k);
}
inline void xdel(int p,int pos){
    del(root[p],a[pos]);
    in(root[p],o);
    if (l[p]==r[p]) return;
    int mid=(l[p]+r[p])>>1;
    if (pos<=mid) xdel(p<<1,pos);else xdel((p<<1)|1,pos);
}
inline int qqu(int p,int k){
    if (!p) return -1;
    if (t[p].k>=k) return qqu(t[p].l,k);else{
        int f=qqu(t[p].r,k);
        if (f==-1) return t[p].k;else return f;
    }
}
inline int hju(int p,int k){
    if (!p) return 1e9;
    if (t[p].k<=k) return hju(t[p].r,k);else{
        int f=hju(t[p].l,k);
        if (f==1e9) return t[p].k;else return f;
    }
}
inline int qq(int p,int a,int b,int k){
    if (l[p]==a&&r[p]==b) return qqu(root[p],k);
    int mid=(l[p]+r[p])>>1;
    if (b<=mid) return qq(p<<1,a,b,k);else
    if (a>mid) return qq((p<<1)|1,a,b,k);else
    return max(qq(p<<1,a,mid,k),qq((p<<1)|1,mid+1,b,k));
}
inline int hj(int p,int a,int b,int k){
    if (l[p]==a&&r[p]==b) return hju(root[p],k);
    int mid=(l[p]+r[p])>>1;
    if (b<=mid) return hj(p<<1,a,b,k);else
    if (a>mid) return hj((p<<1)|1,a,b,k);else
    return min(hj(p<<1,a,mid,k),hj((p<<1)|1,mid+1,b,k));
}
inline void pr(int a){
   int l=a/10;
   if(l) pr(l);
   putchar(a-l*10+48);
}
int main(){
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    n=read();m=read();
    srand(n);
    for (register int i=1;i<=n;i++) a[i]=read();
    build(1,1,n);
    int l,r;
    while(m--){
        o=read();
        if (o==1){
            l=read();r=read();o=read();
            pr(qu(1,l,r,o)+1);putchar('\n');
        }else if (o==2){
            l=read();r=read();o=read();
            ll=0;rr=1e8;
            while(ll<rr){
                mid=(ll+rr)>>1;
                w=0;
                p=qu(1,l,r,mid);
                if (p<o&&p+w>=o){
                    ll=mid;
                    break;
                }
                if (p>=o) rr=mid-1;else ll=mid+1;
            }
            pr(ll);putchar('\n');
        }else if (o==3){
            l=read();o=read();
            xdel(1,l);
            a[l]=o;
        }else if (o==4){
            l=read();r=read();o=read();
            pr(qq(1,l,r,o));putchar('\n');
        }else{
            l=read();r=read();o=sread();
            pr(hj(1,l,r,o));putchar('\n');
        }
    }
}

 

posted @ 2016-02-26 14:24  swm_sxt  阅读(251)  评论(0编辑  收藏  举报