Treap求调,感觉是ins出了问题蛋调不出来。悬赏一个关注QAQ
查看原帖
Treap求调,感觉是ins出了问题蛋调不出来。悬赏一个关注QAQ
759274
Stevehim楼主2023/3/30 19:01
#include <bits/stdc++.h>
#define maxn 300010
#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 a[maxn];

struct node {
	int l, r, k, rank;
	bool operator < (const node &a) const {
		return (a.l == l) ? (r < a.r) : (l < a.l);
	}
} b[maxn];


int add(int val) {
	v[++sum] = val;
	size[sum] = 1;
	num[sum] = 1;
	rd[sum] = rand();
	return sum;
}

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 = add(x);
		return;
	}
	if (v[p] == x) { //有一个数和x重复
		num[p]++; //个数加一
		size[p]++;
		//这里就是不用pushup了,直接size加一岂不美哉
		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;
}
int l, r, k;
int ans[maxn];

int main() {
//	freopen("3.in", "r", stdin);
	rd[0] = -1;
	int n, m;
	read(n);
	read(m);
	for (register int i = 1; i <= n; i++) {
		read(a[i]);
	}
	for (register int i = 1; i <= m; i++) {
		read(b[i].l);
		read(b[i].r);
		read(b[i].k);
		b[i].rank = i;
	}
	sort(b + 1, b + m + 1);
	int head = 1, tail = 0;
	for (int i = 1; i <= m; i++) {
		while (tail < b[i].r)
			ins(rt, add(a[++tail]));
		while (head < b[i].l)
			del(rt, a[head++]);
		ans[b[i].rank] = v[find(rt, b[i].k)];
	}
	for (int i = 1; i <= m; i++) {
		cout << ans[i] << endl;
	}
	return 0;
}



2023/3/30 19:01
加载中...