题目背景
小明准备给小红送一束花,以表达他对小红的爱意。他在花店看中了一些花,准备用它们包成花束。

题目描述
这些花都很漂亮,每朵花有一个美丽值W,价格为C。

小明一开始有一个空的花束,他不断地向里面添加花。他有以下几种操作:

操作 含义

1 W C 添加一朵美丽值为W,价格为C的花。

3 小明觉得当前花束中最便宜的一朵花太廉价,不适合送给小红,所以删除最便宜的一朵花。

2 小明觉得当前花束中最贵的一朵花太贵,他心疼自己的钱,所以删除最贵的一朵花。

-1 完成添加与删除,开始包装花束

若删除操作时没有花,则跳过删除操作。

如果加入的花朵价格已经与花束中已有花朵价格重复,则这一朵花不能加入花束。

请你帮小明写一个程序,计算出开始包装花束时,花束中所有花的美丽值的总和,以及小明需要为花束付出的总价格。

输入格式
若干行,每行一个操作,以-1结束。

输出格式
一行,两个空格隔开的正整数表示开始包装花束时,花束中所有花的美丽值的总和。以及小明需要为花束付出的总价格。

输入输出样例
输入 #1复制

1 1 1
1 2 5
2
1 3 3
3
1 5 2
-1
输出 #1复制
8 5
说明/提示
对于20%数据,操作数<=100,1<=W,C<=1000。

对于全部数据,操作数<=100000,1<=W,C<=1000000。


一道平衡树的裸题。

于是我选择用 fhq_treap来做。


因为我们要维护两个信息,一个美丽度,一个价值。所以开两个数组记录即可。由于这道题我们按照价值建立平衡树,而且每次需要找到价值最大的和最小的,于是我们需要按照个数split,又要插入数据,所以要权值split,所以要写两个。

最后dfs一遍,统计答案即可。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int sw,sc;
int ch[N][2],w[N],c[N],sz[N],pri[N],num,root,x,y,z;
inline void push_up(int p){
	sz[p]=sz[ch[p][0]]+sz[ch[p][1]]+1;
}
inline int new_node(int a,int b){
	sz[++num]=1; w[num]=a; c[num]=b; pri[num]=rand(); return num;
}
void split(int now,int k,int &x,int &y){
	if(!now)	return (void)(x=y=0);
	if(c[now]<=k)	x=now,split(ch[now][1],k,ch[now][1],y);
	else	y=now,split(ch[now][0],k,x,ch[now][0]);
	push_up(now);
}
void split1(int now,int k,int &x,int &y){
	if(!now)	return (void)(x=y=0);
	if(k<=sz[ch[now][0]])	y=now,split1(ch[now][0],k,x,ch[now][0]);
	else	x=now,split1(ch[now][1],k-sz[ch[now][0]]-1,ch[now][1],y);
	push_up(now);	
}
int merge(int x,int y){
	if(!x||!y)	return x+y;
	if(pri[x]<pri[y]){
		ch[x][1]=merge(ch[x][1],y);	push_up(x);	return x;
	}else{
		ch[y][0]=merge(x,ch[y][0]); push_up(y);	return y;
	}
}
inline void del1(){
	split1(root,sz[root]-1,root,y);
}
inline void del2(){
	split1(root,1,x,root);
}
void dfs(int now){
	if(!now)	return ;
	sw+=w[now];	sc+=c[now];
	dfs(ch[now][0]);	dfs(ch[now][1]);
}
signed main(){
	while(1){
		int op;	scanf("%lld",&op);	if(op==-1)	break;
		if(op==2)	del1();
		else if(op==3)	del2();
		else{
			int a,b;	scanf("%lld %lld",&a,&b);
			split(root,b,x,y);	split(x,b-1,x,z);
			if(sz[z]!=0)	root=merge(merge(x,z),y);
			else	root=merge(merge(x,new_node(a,b)),y);
		}
	}
	dfs(root);	printf("%lld %lld\n",sw,sc);
	return 0;
}