Treap求调++QAQ
  • 板块P2073 送花
  • 楼主Stevehim
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/3/30 19:48
  • 上次更新2023/10/23 20:01:10
查看原帖
Treap求调++QAQ
759274
Stevehim楼主2023/3/30 19:48
#include <bits/stdc++.h>
#define maxn 1000100
#define inf 2000000005
//板子好啊
using namespace std;
typedef long long ll;
int sum = 0, rt = 0;
int size[maxn]; //存储大小
int v[maxn];
int num[maxn];
int rd[maxn]; //随机数
int son[maxn][2];
int last = 0;
int o1, o2, o3; //3个选项
int mi = inf;
int ma = 0;
int flowers = 0;
int flower[maxn]; //用于映射某价格的花美丽值为多少
//注意:这里的平衡树用来存取价格
bool money[maxn];

void pushup(int p) {
	//用儿子更新父节点p的节点数,类似于线段树的sum操作
	size[p] = size[son[p][0]] + size[son[p][1]] + num[p];
	//注意此处p本身有的数量可不是两儿子相加
}

void rotate(int &p, int d) { //旋转操作,d为左旋/右旋
	int k = son[p][d ^ 1];
	son[p][d ^ 1] = son[k][d]; //p的左/右儿子变成k的右/左儿子,1^1 = 0,0 ^ 1 = 1;
	son[k][d] = p;
	pushup(p);
	pushup(k);
	p = k;
}

void ins(int &p, int x) {
	//插入节点(以p为根)
	if (!p) { //节点为空则开辟空结点
		p = ++sum;
		size[p] = num[p] = 1;
		v[p] = x;
		rd[p] = rand(); //随机
		return;
	}
	if (v[p] == x) { //有一个数和x重复
		return; //直接返回,因为冲突了
	}
	int d = (x > v[p]); //妙,根据大于的bool(1/0),用son数组直接达到效果
	ins(son[p][d], x);
	if (rd[p] < rd[son[p][d]])
		rotate(p, d ^ 1); //如果小于说明其应该左旋
	pushup(p);
}

void del(int &p, int x) {
	if (!p)
		return; //没有我删什么?
	if (x < v[p])
		del(son[p][0], x); //按性质递归下去
	else if (x > v[p])
		del(son[p][1], x);
	else {
		if (!son[p][1] && !son[p][0]) { //没有孩子
			num[p]--;
			size[p]--;
			if (num[p] == 0)
				p = 0; //不存在了
		} else if (son[p][0] && !son[p][1]) {
			rotate(p, 1);
			del(son[p][1], x); //尝试提出优化
		} else if (son[p][1] && !son[p][0]) {
			rotate(p, 0);
			del(son[p][0], x); //尝试提出优化
		} else if (son[p][0] && son[p][1]) {
			int d = (rd[son[p][0]] > rd[son[p][1]]);
			rotate(p, d);
			del(son[p][d], x);
		}
	}
	pushup(p); //最后上传
}

int _rank(int p, int x) { //注意:此处排名为从小到大
	if (!p)
		return 1;
	if (v[p] == x)
		return size[son[p][0]] + 1;
	if (v[p] < x)
		return size[son[p][0]] + num[p] + _rank(son[p][1], x);
	if (v[p] > x)
		return _rank(son[p][0], x);
}

int find(int p, int x) {
	if (!p)
		return 0;
	if (size[son[p][0]] >= x)
		return find(son[p][0], x);
	else if (size[son[p][0]] + num[p] < x)
		return find(son[p][1], x - num[p] - size[son[p][0]]);
	else
		return v[p]; //都等于了,对吧
}

int pre(int p, int x) {
	if (!p)
		return -inf;
	if (v[p] >= x)
		return pre(son[p][0], x);
	else
		return max(v[p], pre(son[p][1], x));
}

int suc(int p, int x) {
	if (!p)
		return inf;
	if (v[p] <= x)
		return suc(son[p][1], x);
	else
		return min(v[p], suc(son[p][0], x)); //因为v[p]已知的比x大,那么要找是否存在比v[p]小的数
}

template<typename T>inline void read(T &ff) {
	T rr = 1;
	ff = 0;
	register char ch = getchar();
	while (!isdigit(ch)) {
		if (ch == '-')
			rr = -1;
		ch = getchar();
	}
	while (isdigit(ch)) {
		ff = (ff << 1) + (ff << 3) + (ch ^ 48);
		ch = getchar();
	}
	ff *= rr;
}

void build() {
	long long ans1 = 0;
	long long ans2 = 0;
	for (int i = 1; i <= sum; i++) {
		if (num[i]) {
			ans1 += v[i];
			ans2 += flower[v[i]];
		}

	}
	cout << ans2 << ' ' << ans1;
}

int main() {
	freopen("1.in", "r", stdin);
	while (1) {
		read(o1);
		if (o1 == -1) {
			build();
			break;
		} else if (o1 == 1) {
			read(o2);
			read(o3);
			if (!money[o3]) {
				flowers++;
				ins(rt, o3);
				flower[o3] = o2;
				mi = min(mi, o3);
				ma = max(ma, o3);
				money[o3] = true;
			}
		} else if (o1 == 2) {
			if (flowers >= 1) {
				del(rt, ma);
				flower[ma] = 0;
				money[ma] = false;
				flowers--;
			}
		} else {
			if (flowers >= 1) {
				del(rt, mi);
				flower[mi] = 0;
				money[mi] = false;
				flowers--;
			}

		}
	}
	return 0;
}
2023/3/30 19:48
加载中...