hdu 5412 CRB and Queries 求动态区间第k小 树套树

题意:
给n个数,然后有两个操作
1.把第i个点的值修改为v
2.求[l,r]区间内第k小的数

树状数组+平衡树。
我写了两份代码:树状数组+SBT和树状数组+Treap
代码:

//author: CHC
//First Edit Time:  2015-08-20 14:10
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
#include <time.h>
using namespace std;
typedef long long LL;
const int MAXN=1e+5 + 1000;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();
struct SBT
{
    int left,right,size,key;
    void Init()
    {
        left=right=0;
        size=1;
    }
}tree[MAXN*30];
int tot,root[MAXN<<2],n;
void left_rotate(int &x)//左旋
{
    int y=tree[x].right;
    tree[x].right=tree[y].left;
    tree[y].left=x;
    tree[y].size=tree[x].size;
    tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
    x=y;
}
void right_rotate(int &x)//右旋
{
    int y=tree[x].left;
    tree[x].left=tree[y].right;
    tree[y].right=x;
    tree[y].size=tree[x].size;
    tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
    x=y;
}
void maintain(int &x,int flag)
{
    if(flag==0)
    {
        if(tree[tree[tree[x].left].left].size > tree[tree[x].right].size)
            right_rotate(x);
        else if(tree[tree[tree[x].left].right].size > tree[tree[x].right].size)
            left_rotate(tree[x].left),right_rotate(x);
        else return;
    }
    else
    {
        if(tree[tree[tree[x].right].right].size > tree[tree[x].left].size)
            left_rotate(x);
        else if(tree[tree[tree[x].right].left].size > tree[tree[x].left].size)
            right_rotate(tree[x].right),left_rotate(x);
        else return;
    }
    maintain(tree[x].left,0);
    maintain(tree[x].right,1);
    maintain(x,0);
    maintain(x,1);
}
//插入元素,相同元素放在右子树中
void insert(int &x,int key)
{
    if(x==0)
    {
        x=++tot;
        tree[x].Init();
        tree[x].key=key;
    }
    else
    {
        tree[x].size++;
        if(key<tree[x].key)insert(tree[x].left,key);
        else insert(tree[x].right,key);
        maintain(x,key>=tree[x].key);
    }
}
//删除key值的元素
int del(int &x,int key)
{
    if(!x)return 0;
    tree[x].size--;
    if(key==tree[x].key || (key<tree[x].key&&tree[x].left==0)
            || (key>tree[x].key&&tree[x].right==0))
    {
        if(tree[x].left && tree[x].right)
        {
            int p=del(tree[x].left,key+1);
            tree[x].key=tree[p].key;
            return p;
        }
        else
        {
            int p=x;
            x=tree[x].left+tree[x].right;
            return p;
        }
    }
    else return del(key<tree[x].key?tree[x].left:tree[x].right,key);
}
int _rank(int x,int val){
    if(x==0)return 0;
    if(tree[x].key<=val)return tree[tree[x].left].size+1+_rank(tree[x].right,val);
    return _rank(tree[x].left,val);
}
void print(int x,int d){
    if(!x)return ;
    printf("%d %d\n",tree[x].key,d);
    print(tree[x].left,d+1);print(tree[x].right,d+1);
}
int A[MAXN];
void Add(int x,int v){
    while(x<=n){
        //printf("x:%d\n",x);
        insert(root[x],v);
        x+=x&-x;
    }
}
void Del(int x,int v){
    while(x<=n){
        del(root[x],v);
        x+=x&-x;
    }
}
int Sum(int x,int v){
    int cnt=0;
    while(x>0){
        cnt+=_rank(root[x],v);
        x-=x&-x;
    }
    return cnt;
}
struct Q {
    int type,l,r,v;
}cs[MAXN];
int res[MAXN*2];
int main()
{
    //int size = 256 << 20; // 256MB  
    //char *p = (char*)malloc(size) + size;  
    //__asm__("movl %0, %%esp\n" :: "r"(p));
    //freopen("1007.in","r",stdin);
    //freopen("10071.out","w",stdout);
    //time_t now=clock();
    int q;
    while(~scanf("%d",&n)){
        memset(root,0,sizeof(root));
        tot=0;
        res[0]=0;
        for(int i=1;i<=n;i++)scanf("%d",&A[i]),res[++res[0]]=A[i];
        scanf("%d",&q);
        for(int i=0;i<q;i++){
            scanf("%d",&cs[i].type);
            if(cs[i].type==1){
                scanf("%d%d",&cs[i].l,&cs[i].v);
                res[++res[0]]=cs[i].v;
            }
            else {
                scanf("%d%d%d",&cs[i].l,&cs[i].r,&cs[i].v);
            }
        }
        sort(res+1,res+1+res[0]);
        res[0]=unique(res+1,res+1+res[0])-res-1;
        for(int i=0;i<q;i++){
            if(cs[i].type==1){
                cs[i].v=lower_bound(res+1,res+1+res[0],cs[i].v)-res;
            }
        }
        //printf("res0:%d\n",res[0]);
        //for(int i=1;i<=res[0];i++)printf("%d ",res[i]);
        //puts("");
        for(int i=1;i<=n;i++)A[i]=lower_bound(res+1,res+1+res[0],A[i])-res;
        //for(int i=1;i<=n;i++)printf("%d ",A[i]);
        //puts("");
        //build(1,n,1);
        //print(root[1],0);
        //puts("here__");
        for(int i=1;i<=n;i++){
            Add(i,A[i]);
        }
        //puts("here");
        for(int i=0;i<q;i++){
            if(cs[i].type==1){
                //update(1,n,1,cs[i].l,cs[i].v);
                Del(cs[i].l,A[cs[i].l]);
                Add(cs[i].l,cs[i].v);
                A[cs[i].l]=cs[i].v;
            }
            else {
                int l=1,r=res[0],ans=res[0];
                while(l<=r){
                    int mid=(l+r)>>1;
                    int t=Sum(cs[i].r,mid)-Sum(cs[i].l-1,mid);
                    if(t>=cs[i].v){
                        ans=mid;
                        r=mid-1;
                    }
                    else l=mid+1;
                }
                printf("%d\n",res[ans]);
            }
        }
    }
    //printf("%.2lf\n",1.0*(clock()-now)/CLOCKS_PER_SEC);
    return 0;
}

代码2:

//author: CHC
//First Edit Time:    2015-08-20 12:15
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
using namespace std;
typedef long long LL;
const int MAXN=1e+5 + 1000;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();
class Treap {
    public:
        struct node {
            node *ch[2];
            int v,p,sz;
            node(int _v,node *_n){ v=_v; ch[0]=ch[1]=_n; p=rand(); sz=1; }
            void update(){sz=ch[0]->sz+ch[1]->sz+1;}
            void fixch(node *left,node *right){ch[0]=left;ch[1]=right;}
        };
        node *root,*null;
        Treap(){
            null=new node(0,0);
            null->fixch(null,null); null->sz=0;
            root=null;
        }
        void rotate(node *&t,bool d){
            node *_t=t->ch[d];
            t->ch[d]=_t->ch[!d];
            _t->ch[!d]=t;
            t->update();
            _t->update();
            t=_t;
        }
        void __insert(node *&t,int val){
            if(t==null){
                t=new node(val,null);
                return ;
            }
            bool d=(t->v < val);
            __insert(t->ch[d],val);
            if(t->ch[d]->p < t->p)rotate(t,d);
            t->update();
        }
        void __del(node *&t,int val){
            if(t==null)return ;
            if(t->v==val){
                node *tmp=t;
                if(t->ch[0]==null){
                    t=t->ch[1];
                    delete tmp;
                    return ;
                }
                if(t->ch[1]==null){
                    t=t->ch[0];
                    delete tmp;
                    return ;
                }
                bool d=t->ch[1]->p < t->ch[0]->p;
                rotate(t,d);
                __del(t->ch[!d],val);
            }
            else {
                bool d=(t->v < val);
                __del(t->ch[d],val);
            }
            t->update();
        }
        int __rank(node *t,int val){
            if(t==null)return 0;
            if(t->v <= val)return t->ch[0]->sz+1+__rank(t->ch[1],val);
            //return t->ch[1]->sz+1+__rank(t->ch[0],val);
            return __rank(t->ch[0],val);
        }
        void __clean(node *&t){
            if(t==null)return ;
            if(t->ch[0]!=null)__clean(t->ch[0]);
            if(t->ch[1]!=null)__clean(t->ch[1]);
            delete t;
            t=null;
        }
        void insert(int val){ __insert(root,val); }
        void del(int val){ __del(root,val); }
        int rank(int val){ return __rank(root,val);}
        void clean(){ __clean(root); }
        ~Treap(){ clean(); delete null; }
}tr[MAXN];
#define lson L,mid,rt<<1
#define rson mid+1,R,rt<<1|1
int A[MAXN],n;
void Add(int pos,int v){
    while(pos<=n){
        tr[pos].insert(v);
        pos+=pos&-pos;
    }
}
void Del(int pos,int v){
    while(pos<=n){
        tr[pos].del(v);
        pos+=pos&-pos;
    }
}
int Sum(int pos,int v){
    int cnt=0;
    while(pos>0){
        cnt+=tr[pos].rank(v);
        pos-=pos&-pos;
    }
    return cnt;
}
struct Q {
    int type,l,r,v;
}cs[MAXN];
int res[MAXN*2];
int main()
{
    //int size = 256 << 20; // 256MB  
    //char *p = (char*)malloc(size) + size;  
    //__asm__("movl %0, %%esp\n" :: "r"(p));
    //freopen("1007.in","r",stdin);
    //freopen("10071.out","w",stdout);
    while(~scanf("%d",&n)){
        res[0]=0;
        for(int i=1;i<=n;i++)scanf("%d",&A[i]),res[++res[0]]=A[i];
        int q;
        //printf("%d\n",query(1,n,1,1,n,4));
        scanf("%d",&q);
        for(int i=0;i<q;i++){
            scanf("%d",&cs[i].type);
            if(cs[i].type==1){
                scanf("%d%d",&cs[i].l,&cs[i].v);
                res[++res[0]]=cs[i].v;
            }
            else {
                scanf("%d%d%d",&cs[i].l,&cs[i].r,&cs[i].v);
            }
        }
        sort(res+1,res+1+res[0]);
        res[0]=unique(res+1,res+1+res[0])-res-1;
        //printf("res0:%d\n",res[0]);
        //for(int i=1;i<=res[0];i++)printf("%d ",res[i]);
        //puts("");
        for(int i=1;i<=n;i++){
            A[i]=lower_bound(res+1,res+1+res[0],A[i])-res;
        }
        //build(1,n,1);
        for(int i=0;i<q;i++){
            if(cs[i].type==1){
                cs[i].v=lower_bound(res+1,res+1+res[0],cs[i].v)-res;
            }
        }
        for(int i=0;i<=n;i++)tr[i].clean();
        for(int i=1;i<=n;i++){
            Add(i,A[i]);
        }
        for(int i=0;i<q;i++){
            if(cs[i].type==1){
                //while(A[cs[i].l]<=0||A[cs[i].l]>res[0]);
                Del(cs[i].l,A[cs[i].l]);
                Add(cs[i].l,cs[i].v);
                A[cs[i].l]=cs[i].v;
            //update(1,n,1,cs[i].l,cs[i].v);
            }
            else {
                int l=1,r=res[0],ans=res[0];
                while(l<=r){
                    int mid=(l+r)>>1;
                    int t=Sum(cs[i].r,mid)-Sum(cs[i].l-1,mid);
                    //if(query(1,n,1,cs[i].l,cs[i].r,mid)>=cs[i].v){
                    if(t>=cs[i].v){
                        ans=mid;
                        r=mid-1;
                    }
                    else l=mid+1;
                }
                printf("%d\n",res[ans]);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值