洛谷 P1486 & LOJ 10145 -「一本通 4.6 练习 2」郁闷的出纳员

题面

题目传送门

思路

看到题目的插入、删除和查询第 k 大操作,就想到了 Treap。

但是全部员工加减工资怎么办?仔细一看,这两种操作总条数不会超过 100,所以遍历整棵树更改数值就好了。

在增加工资的时候,一定不会有人离开。

在减少工资的时候,我们不断找工资底线 k 的前驱,如果它存在,就删除它。

最后的离开人数就是插入操作的次数减去最后的人数。

代码

#include<bits/stdc++.h>
using namespace std;
struct node{
	long long x,y,l,r,size,cnt;
};
node s[1000001];
long long n,q,top=0,cnt=0,len=0,k;
long long root=0;
void dfs(long long x,int k){
	if (!x){
		return;
	}
	s[x].x+=k;
	dfs(s[x].l,k);
	dfs(s[x].r,k);
}
void update(long long x){
	s[x].size=s[s[x].l].size+s[s[x].r].size+s[x].cnt;
}
void rotr(long long &x){
	long long l=s[x].l;
	s[x].l=s[l].r;
	s[l].r=x;
	s[l].size=s[x].size;
	update(x);
	x=l;
}
void rotl(long long &x){
	long long r=s[x].r;
	s[x].r=s[r].l;
	s[r].l=x;
	s[r].size=s[x].size;
	update(x);
	x=r;
}
void add(long long &x,long long data){
	if (!x){
		x=++top;
		s[x].x=data;
		s[x].y=rand()%19260817;
		s[x].cnt=1;
		s[x].size=1;
		s[x].l=0;
		s[x].r=0;
		return;
	}
	s[x].size++;
	if (s[x].x==data){
		s[x].cnt++;
	}else if (data<s[x].x){
		add(s[x].l,data);
		if (s[x].y>s[s[x].l].y){
			rotr(x);
		}
	}else{
		add(s[x].r,data);
		if (s[x].y>s[s[x].r].y){
			rotl(x);
		}
	}
}
void del(long long &x,long long data){
	if (s[x].x==data){
		if (s[x].cnt>1){
			s[x].cnt--;
			s[x].size--;
			return;
		}
		if (!s[x].l||!s[x].r){
			x=s[x].l+s[x].r;
			return;
		}
		if (s[s[x].l].y<s[s[x].r].y){
			rotr(x);
			del(x,data);
		}else{
			rotl(x);
			del(x,data);
		}
		return;
	}
	s[x].size--;
	if (data<s[x].x){
		del(s[x].l,data);
	}else{
		del(s[x].r,data);
	}
}
long long pre(long long data){
	long long now=root,res=-2147483647;
	while (now){
		if (s[now].x<data){
			res=s[now].x;
			now=s[now].r;
		}else{
			now=s[now].l;
		}
	}
	return res;
}
long long nxt(long long data){
	long long now=root,res=2147483647;
	while (now){
		if (s[now].x>data){
			res=s[now].x;
			now=s[now].l;
		}else{
			now=s[now].r;
		}
	}
	return res;
}
long long querykth(long long k){
	long long now=root;
	while (now){
		if (s[s[now].l].size<k&&s[s[now].l].size+s[now].cnt>=k){
			return s[now].x;
		}
		if (s[s[now].l].size>=k){
			now=s[now].l;
		}else{
			k-=s[s[now].l].size+s[now].cnt;
			now=s[now].r;
		}
	}
	return 0;
}
long long queryrank(long long data){
	long long now=root,res=0;
	while (now){
		if (data==s[now].x){
			return res+s[s[now].l].size+1;
		}
		if (data<s[now].x){
			now=s[now].l;
		}else{
			res+=s[s[now].l].size+s[now].cnt;
			now=s[now].r;
		}
	}
	return res;
}
void check(){
	int x=pre(k);
	while (x<k&&x!=-2147483647){
		del(root,x);
		len--;
		x=pre(k);
	}
}
int main(){
	srand(time(0));
	cin>>q>>k;
	string t;
	long long x;
	while (q--){
		cin>>t>>x;
		if (t=="I"){
			if (x<k){
				continue;
			}
			len++;
			cnt++;
			add(root,x);
		}
		if (t=="A"){
			dfs(root,x);
		}
		if (t=="S"){
			dfs(root,-x);
			check();
		}
		if (t=="F"){
			if (x>len){
				cout<<"-1"<<endl;
				continue;
			}
			cout<<querykth(len-x+1)<<endl;
		}
	}
	cout<<cnt-len;
}
作者: solstice23
本文采用 CC BY-NC-SA 4.0 协议
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: Telegram @AmashiroNatsukiEars_NoWord Sticker
Source: Telegram Animated Emojis
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
AmashiroNatsukiEars
Telegram Emojis
小恐龙
花!
上一篇
下一篇