zoukankan      html  css  js  c++  java
  • zoj 3612 Median SBT

    维护一个集合,插入与删除操作,每一步结束之后,输出中位数

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define LL long long
    const int maxn = 100010;
    #define ls T[x].l
    #define rs T[x].r
    #define lls T[ls].l
    #define lrs T[ls].r
    #define rls T[rs].l
    #define rrs T[rs].r
    struct SBT{
    	//左子树指针,右子树指针,大小,键值
    	int l,r,sz,key;
    	void init(){
    		l=r=key=0;
    		sz=1;
    	}
    }T[maxn];
    int root,tot; //根的位置以及节点个数
    //左旋转处理
    void l_rot(int &x){
    	int k=rs;
    	rs=T[k].l;
    	T[k].l=x;
    	T[k].sz=T[x].sz;
    	T[x].sz=T[ls].sz+T[rs].sz+1;
    	x=k;
    }
    //右旋转处理
    void r_rot(int &x){
    	int k=ls;
    	ls=T[k].r;
    	T[k].r=x;
    	T[k].sz=T[x].sz;
    	T[x].sz=T[ls].sz+T[rs].sz+1;
    	x=k;
    }
    //调整处理
    void maintain(int &x,bool flag){
    	if(flag){  //更新右子树
    		if(T[rrs].sz>T[ls].sz)
    			l_rot(x);
    		else if(T[rls].sz>T[ls].sz){
    			r_rot(rs);
    			l_rot(x);
    		}
    		else
    			return;
    	}
    	else{   //更新在左子树
    		if(T[lls].sz>T[rs].sz)
    			r_rot(x);
    		else if(T[lrs].sz>T[rs].sz){
    			l_rot(ls);
    			r_rot(x);
    		}
    		else
    			return;
    	}
    	//更新子树,然后再更新根,直到平衡为止
    	maintain(ls,false);
    	maintain(rs,true);
    	maintain(x,false);
    	maintain(x,true);
    }
    //插入新节点
    void insert(int &r,LL k){
    	if(r==0){
    		r=++tot;
    		T[r].init();
    		T[r].key=k;
    	}
    	else{
    		T[r].sz++;
    		if(k<T[r].key)
    			insert(T[r].l,k);
    		else
    			insert(T[r].r,k);
    		//插入后要调整,保证平衡
    		maintain(r,k>=T[r].key);
    	}
    }
    //删除结点,利用的是前驱替换
    int remove(int &r,int k){
    	int d_key;
    	if(!r)
    		return 0;
    	T[r].sz--;
    	//前者说明就是要删的节点,后两者说明不存在此节点
    	if(T[r].key==k||(T[r].l==0&&k<T[r].key)||(T[r].r==0&&k>T[r].key)){
    		d_key=T[r].key;
    		if(T[r].l&&T[r].r)
    			T[r].key=remove(T[r].l,k+1);
    		else
    			r=T[r].l+T[r].r;
    		return d_key;
    	}
    	else return remove(k<T[r].key?T[r].l:T[r].r,k);
    
    }
    int get_pre(int &x,int y,int k) {
        if(x == 0) return y;
        if(k > T[x].key) return get_pre(rs,x,k);
        else return get_pre(ls,y,k);
    }
    int get_next(int &x,int y,int k) {
        if(x == 0) return y;
        if(k < T[x].key) return get_next(ls,x,k);
        else return get_next(rs,y,k);
    }
    //取得第K大的数
    int get_max_Kth(int &x,int k){
    	int t=T[rs].sz+1;
    	if(t==k) return T[x].key;
    	if(t<k) return get_max_Kth(ls,k-t);
    	else return get_max_Kth(rs,k);
    }
    //取得第K小的数
    int get_min_Kth(int &x,int k){
        int t=T[ls].sz+1;
        if(t==k) return T[x].key;
        if(t<k) return get_min_Kth(rs,k-t);
        else return get_max_Kth(ls,k);
    }
    //查找树中是否存在元素
    int find(int &r,LL k){
    	if(!r) return 0;
    	if(T[r].key==k) return 1;
    	if(k<T[r].key) return find(T[r].l,k);
    	else return find(T[r].r,k);
    }
    //获得结点的名次
    int get_rank(int &x,int k) {
        if(k<T[x].key)
            return get_rank(ls,k);
        else if(k>T[x].key)
            return get_rank(rs,k)+T[ls].sz+1;
        else
            return T[ls].sz+1;
    }
    //排序
    void inorder(int &x) {
        if(x == 0) return;
        inorder(ls);
        printf("%d
    ",T[x].key);
        inorder(rs);
    }
    int main(){
    	int t,q;
    
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d",&q);
    		tot=root=0;
    		int cnt=0;
    		int k;
    		char str[10];
    		while(q--){
    			scanf("%s%d",str,&k);
    			if(str[0]=='a'){
    				insert(root,k);
    				cnt++;
    				if(cnt&1) printf("%d
    ",get_max_Kth(root,cnt/2+1));
    				else {
    					LL ans=(LL)get_max_Kth(root,cnt/2)+(LL)get_max_Kth(root,cnt/2+1);
    					if(ans&1)printf("%.1f
    ",ans/2.0);
    					else printf("%lld
    ",ans/2);
    				}
    			}
    			else{
    				if(!find(root,k)) {printf("Wrong!
    ");continue;}
    				cnt--;
    				remove(root,k);
    				if(cnt==0){printf("Empty!
    ");continue;}
    				if(cnt&1) printf("%d
    ",get_max_Kth(root,cnt/2+1));
    				else {
    					LL ans=(LL)get_max_Kth(root,cnt/2)+(LL)get_max_Kth(root,cnt/2+1);
    					if(ans&1)printf("%.1f
    ",ans/2.0);
    					else printf("%lld
    ",ans/2);
    				}
    			}
    
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    API开放平台基于accessToken实现
    web记住我功能的实现
    SpringBoot整合AbstractRoutingDataSource实现读写分离
    手写简化版SpringBoot
    mybatisGenerator
    C程序编译执行过程
    用WaveX实现音频文件的录音
    java学习--数组
    Linux学习笔记--vim
    PHP常量总结
  • 原文地址:https://www.cnblogs.com/tobec/p/3238790.html
Copyright © 2011-2022 走看看