zoukankan      html  css  js  c++  java
  • 【NOI2004】【洛谷P1486】郁闷的出纳员(Splay写法)

    传送门

    平衡树简单题

    因为是全局加减

    维护一下全局一个addadd表示当前工资加减情况

    删除就把最低要求的后继SplaySplay到根

    然后把左儿子删去就是了

    因为个人代码是旋转了后继,为了保证有后继要先插入一个极大值


    代码:

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=100006;
    char c[5];
    int fa[N],son[N][2],rt,tot,n,add,mn,num,ans,siz[N],val[N],cnt[N];
    #define lc(u) son[u][0]
    #define rc(u) son[u][1]
    inline void pushup(int u){
    	siz[u]=siz[lc(u)]+siz[rc(u)]+cnt[u];
    }
    inline void rotate(int v){
    	int u=fa[v],z=fa[u];
    	int t=(rc(u)==v);
    	son[z][rc(z)==u]=v;
    	fa[v]=z;
    	son[u][t]=son[v][t^1];
    	fa[son[v][t^1]]=u;
    	fa[u]=v,son[v][t^1]=u;
    	pushup(u),pushup(v);
    }
    inline void splay(int v,int goal){
    	while(fa[v]!=goal){
    		int u=fa[v],z=fa[u];
    		if(z!=goal)
    			(lc(z)==u)^(lc(u)==v)?rotate(v):rotate(u);
    		rotate(v);
    	}
    	if(!goal)rt=v;
    }
    inline void insert(int x){
    	int u=rt,f=0;
    	while(u&&val[u]!=x){
    		f=u,u=son[u][x>val[u]];
    	}
    	if(u)cnt[u]++;
    	else{
    		u=++tot;if(f)son[f][x>val[f]]=u;
    		fa[u]=f;val[u]=x,siz[u]=cnt[u]=1;
    	}
    	splay(u,0);
    }
    inline void find(int x){
    	int u=rt;
    	if(!u)return;
    	while(son[u][x>val[u]]&&val[u]!=x)
    		u=son[u][x>val[u]];
    	splay(u,0);
    }
    inline int nxt(int x){
    	find(x);
    	int u=rt;
    	if(val[u]>=x)return u;
    	u=rc(u);
    	while(lc(u))u=lc(u);
    	return u;
    }
    inline int kth(int k){
    	int u=rt;
    	if(siz[u]<k||k<=0)return -1;
    	while(224){
    		int v=lc(u);
    		if(siz[v]+cnt[u]<k){
    			k-=siz[v]+cnt[u];u=rc(u);
    		}
    		else{
    			if(siz[v]>=k)u=v;
    			else return val[u];
    		}
    	}
    }
    int main(){
    	n=read(),mn=read();insert(199999999);
    	for(int i=1;i<=n;i++){
    		scanf("%s",c);
    		int x=read();
    		if(c[0]=='I'){
    			if(x>=mn){
    				insert(x-add);num+=1;
    			}
    		}
    		else if(c[0]=='A'){
    			add+=x;
    		}
    		else if(c[0]=='S'){
    			add-=x;
    			int lv=nxt(mn-add);
    			splay(lv,0);
    			ans+=siz[lc(rt)];
    			num-=siz[lc(rt)];
    			cnt[lc(rt)]=siz[lc(rt)]=0,lc(rt)=0,siz[0]=0;
    			pushup(rt);
    		}
    		else{
    			int p=kth(num-x+1);
    			cout<<(p==-1?p:p+add)<<'
    ';
    		}
    		//cout<<num<<'
    ';
    	}
    	cout<<ans<<'
    ';
    }
    
  • 相关阅读:
    三大家族的作用和区别
    正则表达式
    Math的方法
    数组API方法
    面向对象方法
    数组的常用方法
    对象和数组的遍历方法
    js运算符(运算符的结合性)
    i++和++i的运算符
    flex
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366340.html
Copyright © 2011-2022 走看看