bzoj 3196: Tyvj 1730 二逼平衡树.

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3196: Tyvj 1730 二逼平衡树.相关的知识,希望对你有一定的参考价值。

3196: Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 4163  Solved: 1598
[Submit][Status][Discuss]

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可能为负数
 
线段树套splay模板题
 
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 50010
#define maxm 3000010
struct Segment_tree {
    int l,r,root,Max,Min;
}t[maxn<<2];
int data[maxn],size[maxm],ch[maxm][2];
int fa[maxm],cnt[maxm],num[maxm];
int n,m,sz=0;
inline int input() {
    int x=0,a=1;char c=getchar();
    for(;c<‘0‘||c>‘9‘;c=getchar())
        if(c==‘-‘) a=-1;
    for(;c>=‘0‘&&c<=‘9‘;c=getchar())
        x=x*10+c-‘0‘;
    return x*a;
}
inline void updata(int now) {
    int l=ch[now][0],r=ch[now][1];
    size[now]=size[l]+size[r]+cnt[now];
    return;
}
inline void updataseg(int now) {
    int lc=now<<1,rc=now<<1|1;
    t[now].Max=max(t[lc].Max,t[rc].Max);
    t[now].Min=min(t[lc].Min,t[rc].Min);
    return;
}
inline int son(int x) {
    return ch[fa[x]][1]==x;
}
void rotate(int &root,int x) {
    int y=fa[x],z=fa[y];
    int b=son(x),c=son(y),a=ch[x][!b];
    if(z) ch[z][c]=x;
    else root=x;
    fa[x]=z;
    if(a) fa[a]=y;
    ch[y][b]=a;
    ch[x][!b]=y;
    fa[y]=x;
    updata(y);
    updata(x);
    return;
}
void splay(int &root,int x,int i) {
    while(fa[x]!=i) {
        int y=fa[x],z=fa[y];
        if(z==i) rotate(root,x);
        else {
            if(son(x)==son(y)) {
                rotate(root,y);
                rotate(root,x);
            } else {
                rotate(root,x);
                rotate(root,x);
            }
        }
    }
    return;
}
void insert(int &k,int c) {
    if(k==0) {
        k=++sz;
        size[k]=cnt[k]=1;
        num[k]=c;
        return;
    }
    if(num[k]==c) cnt[k]++;
    else if(num[k]<c) {
        insert(ch[k][1],c);
        fa[ch[k][1]]=k;
    } else {
        insert(ch[k][0],c);
        fa[ch[k][0]]=k;
    }
    updata(k);
    return;
}
void buildseg(int now,int l,int r) {
    t[now].l=l,t[now].r=r;
    if(l==r) return;
    int mid=l+r>>1;
    buildseg(now<<1,l,mid);
    buildseg(now<<1|1,mid+1,r);
    return;
}
int getpre(int rt,int k) {
    int pos=rt,ret;
    while(pos) {
        if(num[pos]>=k) pos=ch[pos][0];
        else ret=pos,pos=ch[pos][1];
    }
    return ret;
}
int getsuf(int rt,int k) {
    int pos=rt,ret;
    while(pos) {
        if(num[pos]<=k) pos=ch[pos][1];
        else ret=pos,pos=ch[pos][0];        
    }
    return ret;
}
int getk(int rt,int k) {
    if(num[rt]==k) return rt;
    if(num[rt]<k) return getk(ch[rt][1],k);
    if(num[rt]>k) return getk(ch[rt][0],k);
}
void build(int rt,int pos,int x) {
    insert(t[rt].root,x);
    if(t[rt].l==t[rt].r) {
        t[rt].Max=t[rt].Min=x;
        return;
    }
    int mid=t[rt].l+t[rt].r>>1;
    if(pos<=mid) build(rt<<1,pos,x);
    else build(rt<<1|1,pos,x);
    updataseg(rt);
    return;
}
void dfsseg(int rt) {
    int x=getsuf(t[rt].root,-1);
    int y=getpre(t[rt].root,1e8+1);
    splay(t[rt].root,x,0);
    size[x]++;
    ch[x][0]=++sz;
    fa[sz]=x;
    size[sz]=cnt[sz]=1;
    num[sz]=-1;
    splay(t[rt].root,y,0);
    size[y]++;
    ch[y][1]=++sz;
    fa[sz]=y;
    size[sz]=cnt[sz]=1;
    num[sz]=1e8+1;
    if(t[rt].l==t[rt].r) return;
    dfsseg(rt<<1);
    dfsseg(rt<<1|1);
    return;
}
int getmax(int rt,int l,int r) {
    if(l<=t[rt].l&&t[rt].r<=r) return t[rt].Max;
    int mid=t[rt].l+t[rt].r>>1,ret=-1;
    if(l<=mid) ret=max(ret,getmax(rt<<1,l,r));
    if(mid<r) ret=max(ret,getmax(rt<<1|1,l,r));
    return ret; 
}
int getmin(int rt,int l,int r) {
    if(l<=t[rt].l&&t[rt].r<=r) return t[rt].Min;
    int mid=t[rt].l+t[rt].r>>1,ret=1e8+1;
    if(l<=mid) ret=min(ret,getmin(rt<<1,l,r));
    if(mid<r) ret=min(ret,getmin(rt<<1|1,l,r));
    return ret;
}
int query_order(int rt,int l,int r,int k) {
    if(l<=t[rt].l&&t[rt].r<=r) {
        int p=getpre(t[rt].root,k);
        splay(t[rt].root,p,0);
        return size[p]-size[ch[p][1]]-1;
    }
    int mid=t[rt].l+t[rt].r>>1,ret=0;
    if(l<=mid) ret+=query_order(rt<<1,l,r,k);
    if(mid<r) ret+=query_order(rt<<1|1,l,r,k);
    return ret;
}
void del(int &rt,int k) {
    int x=getk(rt,k);
    if(cnt[x]>1) {
        splay(rt,x,0);
        cnt[x]--;
        size[x]--;
    } else {
        int p=getpre(rt,k),s=getsuf(rt,k);
        splay(rt,p,0);
        splay(rt,s,p);
        ch[s][0]=0;
    }
    return;
}
void modify(int rt,int pos,int pre,int now) {
    del(t[rt].root,pre);
    insert(t[rt].root,now);
    if(t[rt].l==t[rt].r) {
        t[rt].Max=t[rt].Min=now;
        return;
    }
    int mid=t[rt].l+t[rt].r>>1;
    if(pos<=mid) modify(rt<<1,pos,pre,now);
    else modify(rt<<1|1,pos,pre,now);
    updataseg(rt);
    return;
}
int query_pre(int rt,int l,int r,int k) {
    if(l<=t[rt].l&&t[rt].r<=r)
        return num[getpre(t[rt].root,k)];
    int mid=t[rt].l+t[rt].r>>1,ret=-1;
    if(l<=mid) ret=max(ret,query_pre(rt<<1,l,r,k));
    if(mid<r) ret=max(ret,query_pre(rt<<1|1,l,r,k));
    return ret;
}
int query_suf(int rt,int l,int r,int k) {
    if(l<=t[rt].l&&t[rt].r<=r)
        return num[getsuf(t[rt].root,k)];
    int mid=t[rt].l+t[rt].r>>1,ret=1e8+1;
    if(l<=mid) ret=min(ret,query_suf(rt<<1,l,r,k));
    if(mid<r) ret=min(ret,query_suf(rt<<1|1,l,r,k));
    return ret;
}
int query_number(int L,int R,int k) {
    int l=1,r=getmax(1,L,R),mid,ret,tmp;
    while(l<=r) {
        mid=l+r>>1;
        tmp=query_order(1,L,R,mid);
        if(tmp<k) ret=mid,l=mid+1;
        else r=mid-1;
    }
    return ret;
}
int main() {
    n=input(),m=input();
    buildseg(1,1,n);
    for(int i=1;i<=n;i++) data[i]=input();
    for(int i=1;i<=n;i++) build(1,i,data[i]);
    dfsseg(1);
    while(m--) {
        int l,r,k,pos,op=input();
        if(op==1) {
            l=input(),r=input(),k=input();
            printf("%d\n",query_order(1,l,r,k)+1);
        } else if(op==2) {
            l=input(),r=input(),k=input();
            printf("%d\n",query_number(l,r,k));
        } else if(op==3) {
            pos=input(),k=input();
            modify(1,pos,data[pos],k);
            data[pos]=k;
        } else if(op==4) {
            l=input(),r=input(),k=input();
            int ans=query_pre(1,l,r,k);
            if(ans!=1e8+1) printf("%d\n",ans);
            else printf("%d\n",getmax(1,l,r));
        } else if(op==5) {
            l=input(),r=input(),k=input();
            int ans=query_suf(1,l,r,k);
            if(ans!=-1) printf("%d\n",ans);
            else printf("%d\n",getmin(1,l,r));
        }
    }
    return 0;
}

  

 
 

以上是关于bzoj 3196: Tyvj 1730 二逼平衡树.的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3196: Tyvj 1730 二逼平衡树

bzoj3196: Tyvj 1730 二逼平衡树

bzoj3196: Tyvj 1730 二逼平衡树

bzoj 3196: Tyvj 1730 二逼平衡树

bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

Bzoj3196 Tyvj 1730 二逼平衡树