洛谷 P1486 [NOI2004] 郁闷的出纳员(Splay)

传送门


解题思路

平衡树板子题。
每次所有的数加或减可以O(1)加或减限制,然后删除掉小于当前限制的点,统计答案。
加点时把原权值减去sum然后扔到Splay中,询问第k大时也要把查询的答案加上一个sum。

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<bitset>
#include<stack>
using namespace std;
template<class T>inline void read(T &x)
{
    x=0;register char c=getchar();register bool f=0;
    while(!isdigit(c))f^=c=='-',c=getchar();
    while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
    if(f)x=-x;
}
template<class T>inline void print(T x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)print(x/10);
    putchar('0'+x%10);
}
const int maxn=3e5+5;
int n,rt,cnt,ans;
long long sum,m;
struct node{
	int siz,cnt,son[2],fa;
	long long val;
}tr[maxn];
void init(){
	tr[rt].son[0]=tr[rt].son[1]=tr[rt].fa=tr[rt].siz=tr[rt].cnt=0;
	rt=0;
}
int New(long long val,int fa){
	cnt++;
	tr[cnt].val=val;
	tr[cnt].fa=fa;
	tr[cnt].son[1]=tr[cnt].son[0]=0;
	tr[cnt].cnt=tr[cnt].siz=1;
	return cnt;
}
void update(int x){
	tr[x].siz=tr[x].cnt;
	if(tr[x].son[0]) tr[x].siz+=tr[tr[x].son[0]].siz;
	if(tr[x].son[1]) tr[x].siz+=tr[tr[x].son[1]].siz;
}
void rotate(int x){
	int y=tr[x].fa,z=tr[y].fa;
	int c=(tr[y].son[1]==x);
	tr[tr[x].son[!c]].fa=y;
	tr[x].fa=tr[y].fa;
	tr[y].fa=x;
	if(z) tr[z].son[tr[z].son[1]==y]=x;
	tr[y].son[c]=tr[x].son[!c];
	tr[x].son[!c]=y;
	update(y);
	update(x);
}
void Splay(int x,int goal){
	if(x==goal) return;
	while(tr[x].fa!=goal){
		int y=tr[x].fa,z=tr[y].fa;
		if(z!=goal) ((tr[y].son[0]==x)^(tr[z].son[0]==y))?rotate(x):rotate(y);
		rotate(x);
	}
	if(!goal) rt=x;
}
void insert(long long val){
	if(!rt){
		rt=++cnt;
		tr[rt].val=val;
		tr[rt].cnt=tr[rt].siz=1;
		return;
	}
	int x=rt;
	while(1){
		if(tr[x].val==val){
			tr[x].cnt++;tr[x].siz++;
			Splay(x,0);
			return;
		}
		if(tr[x].son[tr[x].val<val]) x=tr[x].son[tr[x].val<val];
		else{
			tr[x].son[tr[x].val<val]=New(val,x);
			Splay(cnt,0);
			return;
		}
	}
}
long long get_val(int tot){
	if(tot>tr[rt].siz) return -sum-1;
	int x=rt;
	while(1){
		while((tr[x].son[1]?tr[tr[x].son[1]].siz:0)+tr[x].cnt<tot) tot-=(tr[x].son[1]?tr[tr[x].son[1]].siz:0)+tr[x].cnt,x=tr[x].son[0];
		if(tr[x].son[1]==0||tot>tr[tr[x].son[1]].siz){
			return tr[x].val;
		}else{
			x=tr[x].son[1];
		}
	}
}
void work(){
	insert(m-sum);
	if(tr[rt].son[0]) ans+=tr[tr[rt].son[0]].siz;
	tr[rt].son[0]=0;
	update(rt);
	if(tr[rt].cnt>1) tr[rt].cnt--;
	else{
		if(tr[rt].son[1]) tr[tr[rt].son[1]].fa=0,rt=tr[rt].son[1];
		else init();
	}
}
int main(){
	read(n);read(m);
	for(int i=1;i<=n;i++){
		char c=getchar();
		while(c<'A'||c>'Z') c=getchar();
		int x;read(x);
		if(c=='I'){
			if(x<m) continue;
			insert(x-sum);
		}else
		if(c=='A'){
			sum+=x;
			work();
		}else
		if(c=='S'){
			sum-=x;
			work();	
		}else{
			print(get_val(x)+sum);
			puts("");
		}
	}
	print(ans);
	return 0;
}
posted @ 2021-11-15 11:20  尹昱钦  阅读(34)  评论(0编辑  收藏  举报