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

BZOJ:1503: [NOI2004]郁闷的出纳员

时间:2018-01-02 23:29:45      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:print   can   include   stream   scanf   scan   namespace   blog   post   

题解:

比较裸的Splay;

整体修改工资用一个变量Tag维护,相当于Splay里的节点都加上Tag

删除的时候用一个点把走不走的员工给隔开,然后删除一整颗子树

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=500009;
int T,lim;
int ans;

int nn,root;
int tag;
int fa[maxn],ch[maxn][2],siz[maxn],cnt[maxn],ky[maxn];
int Splayinit(){
	ans=root=nn=tag=0;
	fa[0]=ch[0][0]=ch[0][1]=siz[0]=cnt[0]=ky[0]=0;
}

inline int son(int x){
	return ch[fa[x]][1]==x;
}
inline int pushup(int x){
	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+cnt[x];
}

int Rotate(int x){
	int y=fa[x];
	int z=fa[y];
	int b=son(x),c=son(y);
	int a=ch[x][b^1];
	if(z)ch[z][c]=x;
	else root=x;
	fa[x]=z;
	if(a)fa[a]=y;
	ch[y][b]=a;
	fa[y]=x;ch[x][b^1]=y;
	pushup(y);pushup(x);
}

int Splay(int x,int i){
	while(fa[x]!=i){
		int y=fa[x];
		int z=fa[y];
		if(z==i){
			Rotate(x);
		}else{
			if(son(x)==son(y)){
				Rotate(y);Rotate(x);
			}else{
				Rotate(x);Rotate(x);
			}
		}
	}
}

int Ins(int val){
	int x=root,y=0;
	while(x){
		y=x;
		if(ky[x]==val){
			++cnt[x];++siz[x];Splay(x,0);
			return 0;
		}
		if(val>ky[x])x=ch[x][1];
		else x=ch[x][0];
	}
	x=++nn;
	fa[x]=y;ch[x][0]=ch[x][1]=0;
	siz[x]=cnt[x]=1;ky[x]=val;
	if(!y){
		root=x;
	}else{
		if(val>ky[y])ch[y][1]=x;
		else ch[y][0]=x;
	}
	Splay(x,0);
}

int Del(){
	Ins(lim-tag-1);
	ans=ans+siz[ch[root][0]]+cnt[root]-1;
	root=ch[root][1];
	fa[root]=0;
}

int Kth(int k){
	int x=root;
	for(int l;x;){
		l=ch[x][0];
		if(k<=siz[l]){
			x=ch[x][0];
		}else if(k>siz[l]+cnt[x]){
			k-=(siz[l]+cnt[x]);
			x=ch[x][1];
		}else{
			return ky[x];
		}
	}
}

int main(){
	scanf("%d%d",&T,&lim);
	Splayinit();
	while(T--){
		char opty=getchar();
		while((opty<‘A‘)||(opty>‘Z‘))opty=getchar();
		int x;
		scanf("%d",&x);
		if(opty==‘I‘){
			if(x<lim)continue;
			Ins(x-tag);
		}
		if(opty==‘A‘){
			tag+=x;
		}
		if(opty==‘S‘){
			tag-=x;
			Del();
		}
		if(opty==‘F‘){
			if(x>siz[root]){
				printf("-1\n");
			}else{
				x=siz[root]-x+1;
				printf("%d\n",Kth(x)+tag);
			}
		}
	}
	printf("%d\n",ans);
	return 0;
}

  

BZOJ:1503: [NOI2004]郁闷的出纳员

标签:print   can   include   stream   scanf   scan   namespace   blog   post   

原文地址:https://www.cnblogs.com/zzyer/p/8179129.html

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