码迷,mamicode.com
首页 > 其他好文 > 详细

3196: Tyvj 1730 二逼平衡树

时间:2015-05-08 14:55:21      阅读:253      评论:0      收藏:0      [点我收藏+]

标签:

http://www.lydsy.com/JudgeOnline/problem.php?id=3196

分析:
带区间查询和名次询问,线段树套treap

操作1: 查询k在区间内的排名。
求出k-1的名次+1就是k的名次

操作2:查询区间内排名为k的值。
二分枚举权值,调用操作1

操作3:修改某一位值上的数值。
在树上先删除,再插入

操作4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
操作5.查询k在区间内的后继(后继定义为大于x,且最小的数)
在treap树上遍历

//83516 kb  6160 ms C++/Edit
#include <bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=50010;
const int N=3000000;
const int inf=1e8;
using namespace std;
int n,q;
int a[MAXN];
struct node{
    node* ch[2];
    int v,size,r;
    int w;
};
node s[N];
node*ptr=s;
node* null=ptr;
struct Treap{
    node* root;
    void push_up(node* &rt){
        rt->size=rt->ch[0]->size+rt->ch[1]->size+rt->w;
    }
    void newnode(node* &rt,int x){
        rt=++ptr;
        rt->v=x;
        rt->r=rand();
        rt->size=rt->w=1;
        rt->ch[0]=rt->ch[1]=null;
    }
    void init(){
        root=null;
    }
    void rotate(node* &rt,int d){
        node* k=rt->ch[d^1];
        rt->ch[d^1]=k->ch[d];
        k->ch[d]=rt;
        push_up(rt);
        push_up(k);
        rt=k;
    }
    void insert(node* &rt,int x){
        if(rt==null){
            newnode(rt,x);
            return ;
        }
        int d=x<=rt->v?0:1;
        if(rt->v==x){
            rt->w++;
        }else{
            insert(rt->ch[d],x);
            if(rt->ch[d]->r > rt->r) rotate(rt,d^1);
        }
        push_up(rt);
    }

    void remove(node* &rt,int x){
        if(rt==null) return ;
        int d=rt->v <x ?1:0;
        if(rt->v==x){
            if(rt->w>=2){
                rt->w--;
            }
            else{
                if(rt->ch[0]!=null&&rt->ch[1]!=null){
                    int d2=rt->ch[0]->r > rt->ch[1]->r ?1:0;
                    rotate(rt,d2);
                    remove(rt->ch[d2],x);
                }else{
                    if(rt->ch[0]==null) rt=rt->ch[1];
                    else rt=rt->ch[0];
                }
            }
        }else{
            remove(rt->ch[d],x);
        }
        if(rt!=null) push_up(rt);
    }

    void modify(node* &rt,int x,int v){
        remove(rt,x);
        insert(rt,v);
    }

    int findk(node* rt,int k){//名次为k的值
        if(rt==null) return -1;
        int s=rt->ch[0]->size;
        if(s+1==k) return rt->v;
        if(k<=s) return findk(rt->ch[0],k);
        else return findk(rt->ch[1],k-s-1);
    }
    int rank(node* rt,int x){//权值为x的名次
        int s=0;
        while(rt!=null){
            if(rt->v==x) return rt->ch[0]->size+s;
            int d=rt->v>x ?0:1;
            if(d==0) rt=rt->ch[0];
            else{
                s+=rt->ch[0]->size+rt->w;
                rt=rt->ch[1];
            }
        }
        return s;
    }

    int before(node *rt,int x){
        if(rt==null) return 0;
        int res=0;
        if(rt->v< x){
            res=max(res,rt->v);
            res=max(res,before(rt->ch[1],x));
        }else res=max(res,before(rt->ch[0],x));
        return res;
    }

    int after(node* rt,int x){
        if(rt==null) return inf;
        int res=inf;
        if(rt->v>x){
            res=min(res,rt->v);
            res=min(res,after(rt->ch[0],x));
        }
        else res=min(res,after(rt->ch[1],x));
        return res;
    }
    void view(node* rt){
        if(rt==null) return ;
        view(rt->ch[0]);
        cout<<rt->v<<" ";
        view(rt->ch[1]);
    }
};
Treap seg[N];
void init(){
    ptr=s;
    for(int i=1;i<N;++i){
        seg[i].init();
    }
}
void build(int p,int v,int l,int r,int rt){

    seg[rt].insert(seg[rt].root,v);
    if(l==r) return ;
    int m=(l+r)>>1;
    if(p<=m) build(p,v,lson);
    else build(p,v,rson);
}

void update(int p,int x,int v,int l,int r,int rt){
    seg[rt].modify(seg[rt].root,x,v);
    if(l==r) return ;
    int m=(l+r)>>1;
    if(p<=m) update(p,x,v,lson);
    else update(p,x,v,rson);
}
int query1(int L,int R,int v,int l,int r,int rt){
    if(L<=l&&r<=R){
        return seg[rt].rank(seg[rt].root,v);
    }
    int m=(l+r)>>1;
    int res=0;
    if(L<=m) res+=query1(L,R,v,lson);
    if(m<R) res+=query1(L,R,v,rson);
    return res;
}
int query2(int L,int R,int k){
    int l=0,r=inf,mid;
    int ans;
    while(l<=r){
        mid=(l+r)>>1;
        int tmp=query1(L,R,mid,1,n,1);
        if(tmp+1<=k) {
            l=mid+1;
            ans=mid;
        }
        else r=mid-1;
    }
    return ans;
}
int query4(int L,int R,int k,int l,int r,int rt){
    if(L<=l&&r<=R){
        return seg[rt].before(seg[rt].root,k);
    }
    int m=(l+r)>>1;
    int res=0;
    if(L<=m) res=max(res,query4(L,R,k,lson));
    if(m<R) res=max(res,query4(L,R,k,rson));
    return res;
}
int query5(int L,int R,int k,int l,int r,int rt){
    if(L<=l&&r<=R){
        return seg[rt].after(seg[rt].root,k);
    }
    int m=(l+r)>>1;
    int res=inf;
    if(L<=m) res=min(res,query5(L,R,k,lson));
    if(m<R) res=min(res,query5(L,R,k,rson));
    return res;
}
void view(int l,int r,int rt){
    seg[rt].view(seg[rt].root);
    cout<<"-------------"<<endl;
    if(l==r) return ;
    int m=(l+r)>>1;
    view(lson);
    view(rson);
}
int main()
{
//#ifndef ONLINE_JUDGE
//freopen("in.cpp","r",stdin);
//#endif // ONLINE_JUDGE
    int l,r,k,pos,op;
    while(scanf("%d%d",&n,&q)==2){
        init();
        for(int i=1;i<=n;++i) {
            scanf("%d",&a[i]);
            build(i,a[i],1,n,1);
        }
        while(q--){
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d%d",&l,&r,&k);
                printf("%d\n",query1(l,r,k,1,n,1)+1);
            }
            if(op==2){
                scanf("%d%d%d",&l,&r,&k);
                printf("%d\n",query2(l,r,k));
            }
            if(op==3){
                scanf("%d%d",&pos,&k);
                int x=a[pos];
                update(pos,x,k,1,n,1);
                a[pos]=k;
            }
            if(op==4){
                scanf("%d%d%d",&l,&r,&k);
                printf("%d\n",query4(l,r,k,1,n,1));
            }
            if(op==5){
                scanf("%d%d%d",&l,&r,&k);
                printf("%d\n",query5(l,r,k,1,n,1));
            }
        }
    }
    return 0;
}

3196: Tyvj 1730 二逼平衡树

标签:

原文地址:http://blog.csdn.net/u014141559/article/details/45579237

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!