【BZOJ】【P3196】【二逼平衡树】

传送门:

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

刷了一上午……线段树套平衡树,rank支持区间加法,kth不支持,所以算kth就二分rank好了

Code:

#include<cstdio>
#include<climits>
#include<iostream>
#include<algorithm>
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define L (i<<1)
#define R (i<<1|1)
const int maxn=50010;
const int INF=INT_MAX;
using namespace std;
int a[50001];
int rnd(){
	static int KEY=12345678;
	return KEY+=KEY<<2|1;
}
int n,m;
int Left,Right,Find;
struct Treap{  
    struct node{  
        int val;int key,size,s;  
        node *c[2];  
        node(int _val,node *C){  
            val=_val;key=rand();  
            size=1;s=1;  
            c[0]=c[1]=C;  
        }  
        void rz(){  
            size=c[0]->size+c[1]->size+s;  
        }  
    };  
    node *root,*Null;  
    Treap(){  
        Null=new node(0,0);  
        Null->size=0;Null->key=INF;Null->val=0;  
        Null->c[0]=Null->c[1]=Null;  
        root=Null;  
    }  
    void rot(node *&t,bool d){  
        node *p=t->c[d];  
        t->c[d]=p->c[!d];  
        p->c[!d]=t;  
        t->rz();p->rz();  
        t=p;  
    }  
    void _insert(node *&t,int x){  
        if(t==Null){  
            t=new node(x,Null);  
            return ;  
        }     
        if(t->val==x){  
            t->s++;  
            t->size++;  
            return;  
        }  
        bool d=x>t->val;  
        _insert(t->c[d],x);  
        if(t->c[d]->key<t->key)  
            rot(t,d);  
        else  
            t->rz();  
    }  
    void _Delete(node *&t,int x){  
        if(t==Null)return;  
        if(t->val==x){  
            if(t->s>1){  
                t->s--;  
                t->size--;  
                return;  
            }  
            bool d=t->c[1]->key<t->c[0]->key;  
            if(t->c[d]==Null){  
                delete t;  
                t=Null;  
                return ;  
            }  
            rot(t,d);  
            _Delete(t->c[!d],x);  
        }else{  
            bool d=x>t->val;  
            _Delete(t->c[d],x);  
        }  
        t->rz();  
    }  
    int _kth(node *&t,int x){  
        int r=t->c[0]->size;  
        if(t==Null)return 0;  
        else if(x<=r)return _kth(t->c[0],x);  
        else if(x>r+t->s)return _kth(t->c[1],x-r-t->s);  
        else return t->val;  
    }  
    int _rank(node *&t,int x){  
        int r=t->c[0]->size;  
        if(t==Null)return 0;  
        else if(x==t->val){Find=1;return r;} 
        else if(x>t->val){Right++;return r+t->s+_rank(t->c[1],x);}
        else{Left++;return _rank(t->c[0],x);}   
    }  
    void _deb(node *&t){  
        printf("val:%d L:%d R:%d\n",t->val,t->c[0]->val,t->c[1]->val);  
        //printf("key:%d L:%d R:%d\n",t->key,t->c[0]->key,t->c[1]->key);  
        printf("size:%d L:%d R:%d\n",t->size,t->c[0]->size,t->c[1]->size);  
        if(t->c[0]!=Null)_deb(t->c[0]);  
        if(t->c[1]!=Null)_deb(t->c[1]);  
    }  
    void deb(){_deb(root);puts("");}  
    void insert(int x){_insert(root,x);}  
    void del(int x){_Delete(root,x);}  
    int kth(int x){return _kth(root,x);}  
    int rank(int x){return _rank(root,x);}  
    int size(){return root->size;}  
    int _prev(node *&t,int x){  
        if(t==Null)return INT_MIN;  
        if(x<=t->val)return _prev(t->c[0],x);  
        return max(t->val,_prev(t->c[1],x));  
    }  
    int _next(node *&t,int x){  
        if(t==Null)return INT_MAX;  
        if(x>=t->val)return _next(t->c[1],x);  
        return min(t->val,_next(t->c[0],x));  
    }  
    int prev(int x){  
        return _prev(root,x);  
    }  
    int next(int x){  
        return _next(root,x);  
    }   
};  
struct seg_tree{
	Treap t[maxn<<2];
	void build(int i,int l,int r){
		if(l>r)return;		
		for(int o=l;o<=r;o++)
		t[i].insert(a[o]);
		if(l==r)return;
		int mid=l+r>>1;
		build(lson);
		build(rson);
	}
	void change(int i,int l,int r,int pos,int val){
		if(l>r)return;
		t[i].del(a[pos]);
		//a[pos]=val;
		t[i].insert(val);
		if(l==r){
			a[pos]=val;
			return;
		}
		int mid=l+r>>1;
		if(pos<=mid)change(lson,pos,val);
		else change(rson,pos,val);
	}
	int rank(int i,int l,int r,int l0,int r0,int k){
		if(l>r)return 0;
		int ans=0;
		if(l0<=l&&r0>=r)
			return t[i].rank(k);
		int mid=l+r>>1;
		if(l0<=mid)ans+=rank(lson,l0,r0,k);
		if(r0>mid) ans+=rank(rson,l0,r0,k);
		return ans;
	}
	int prev(int i,int l,int r,int l0,int r0,int k){
		if(l>r)return 0;
		int ans=INT_MIN;
		if(l0<=l&&r0>=r)
			return t[i].prev(k);
		int mid=l+r>>1;
		if(l0<=mid)ans=max(ans,prev(lson,l0,r0,k));
		if(r0>mid) ans=max(ans,prev(rson,l0,r0,k));
		return ans;	
	}
	int next(int i,int l,int r,int l0,int r0,int k){
		if(l>r)return 0;
		int ans=INT_MAX;
		if(l0<=l&&r0>=r)
			return t[i].next(k);
		int mid=l+r>>1;
		if(l0<=mid)ans=min(ans,next(lson,l0,r0,k));
		if(r0>mid) ans=min(ans,next(rson,l0,r0,k));
		return ans;	
	}
}T;
void Change(int pos,int k){
	T.change(1,1,n,pos,k);		
}
int Rank(int l,int r,int k){
	Left=Right=Find=0;
	int res=T.rank(1,1,n,l,r,k);
	if(Find)return res+1;
	if(Left==0)return res+1;
	if(Right==0)return res;
	return res+1;
}
int kth(int l0,int r0,int k){
	int l=0,r=int(1e8)+10;
	while(l<r){
		int mid=l+r>>1;

		if(Rank(l0,r0,mid)<=k)
			l=mid+1;
		else
			r=mid;
	}
	return l-1;
}
int prev(int l,int r,int k){
	return T.prev(1,1,n,l,r,k);
}
int next(int l,int r,int k){
	return T.next(1,1,n,l,r,k);
}
int main(){
	scanf("%d%d",&n,&m);

		for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	//	Change(i,a[i]);
	}	
	T.build(1,1,n);
	int opt,l,r,k,pos;
	while(m--){
		scanf("%d",&opt);
		switch(opt){
			case 1:{
				scanf("%d%d%d",&l,&r,&k);
				printf("%d\n",Rank(l,r,k));
				break;
			}
			case 2:{
				scanf("%d%d%d",&l,&r,&k);
				printf("%d\n",kth(l,r,k));
				break;
			}
			case 3:{
				scanf("%d%d",&pos,&k);
				Change(pos,k);
				break;
			}
			case 4:{
				scanf("%d%d%d",&l,&r,&k);
				printf("%d\n",prev(l,r,k));
				break;
			}
			case 5:{
				scanf("%d%d%d",&l,&r,&k);
				printf("%d\n",next(l,r,k));
				break;
			}
		}
	}
	return 0;
} 


你可能感兴趣的:(bzoj,省选)