FHQTreap求调
查看原帖
FHQTreap求调
364848
Bodhi楼主2023/2/12 23:03

rt,样例的第九个数据开始出现问题,初步推测可能是findrk函数和父结点的维护出现问题

#include <bits/stdc++.h>
using namespace std;

const int R = 2e5 + 100;
struct
{
	int lc, rc, key, sz, fa;
	int lb, rb;
} tree[R]; // 以排名为关键字的平衡树,lb、rb记录的是用户编号
int tot, root;
mt19937 rd;
map<int, int> mp; // 以编号为关键字的平衡树
// first:leftbound
// second:node
int crt(int l, int r)
{
	tree[++tot].sz = r - l + 1;
	tree[tot].lb = l;
	tree[tot].rb = r;
	tree[tot].key = rd();
	mp[l] = tot;
	return tot;
}
#define lc(k) tree[k].lc
#define rc(k) tree[k].rc
#define len(k) (tree[k].rb - tree[k].lb + 1)
#define fa(k) tree[k].fa
void pushup(int k)
{
	tree[k].sz = tree[lc(k)].sz + tree[rc(k)].sz + len(k);
	tree[lc(k)].fa = tree[rc(k)].fa = k; // 将父结点和子结点互相连接上(因为如果没有这句就只是父结点连接子结点)
}
int merge(int x, int y)
{
	if (!x || !y)
		return x + y;
	if (tree[x].key < tree[y].key)
	{
		tree[x].rc = merge(tree[x].rc, y);
		pushup(x);
		return x;
	}
	else
	{
		tree[y].lc = merge(x, tree[y].lc);
		pushup(y);
		return y;
	}
}
void splitnode(int k, int sz)
{
	if (len(k) <= sz)
		return; // 如果当前结点不够分裂出新结点,或者本身节点大小就是sz,就直接返回
	int r1 = tree[k].lb + sz - 1;
	int newnode = crt(r1 + 1, tree[k].rb);
	// tree[newnode].key = tree[k].key; // 强制维护堆的性质,不写也行
	tree[k].rb = r1;
	tree[k].rc = merge(newnode, tree[k].rc);
	pushup(k), pushup(rc(k));
}
void split(int k, int sz, int &x, int &y)
{
	if (k == 0)
	{
		x = y = 0;
		return;
	}
	if (tree[lc(k)].sz >= sz)
	{
		y = k;
		split(tree[y].lc, sz, x, tree[y].lc);
	}
	else
	{
		x = k;
		splitnode(x, sz - tree[lc(k)].sz);
		split(tree[x].rc, sz - tree[lc(k)].sz - len(k), tree[x].rc, y);
	}
	pushup(k);
}
int findrk(int id) // 查找左边界的左边还有多少个用户
{
	int x = id, res = 0;
	while (x != root && fa(x) != 0)
	{
		if (rc(fa(x)) == x) // 当前结点是一个右儿子
			res += tree[lc(fa(x))].sz + len(fa(x));
		x = fa(x);
	}
	return res;
}
int a, b, c;
int update(int x, int y)
{
	int id = (--mp.upper_bound(x))->second;
	int rk = findrk(id);
	split(root, rk + x - tree[id].lb, a, b);
	split(b, 1, b, c);
	tree[b].lb = tree[b].rb = y; // 改编号
	mp[y] = b;
	root = merge(merge(a, b), c);
	// int res = rk + x - tree[id].lb + 1;
	// int res = findrk(b);
	return findrk(b) + 1;
}
int tof(int x)
{
	// auto it = --mp.upper_bound(x);
	// int lb = it->first, id = it->second;
	// int rb = tree[id].rb;
	// int res = findrk(id) - (rb - x);

	int id = (--mp.upper_bound(x))->second;
	// cout << '\n'
	// 	 << id << '\n';
	int rk = findrk(id);
	// cout << 'n' << rk;
	split(root, rk + x - tree[id].lb, a, b);
	split(b, 1, b, c);
	// mp[x] = b;
	int res = tree[a].sz + 1;
	root = merge(merge(b, a), c);
	return res;
}
int tol(int x)
{
	int id = (--mp.upper_bound(x))->second;
	int rk = findrk(id);
	split(root, rk + x - tree[id].lb, a, b);
	// cout << '\n'
	// 	 << 'r' << id << '\n';
	split(b, 1, b, c);
	// mp[x] = b;
	int res = tree[a].sz + 1;
	root = merge(merge(a, c), b);
	return res;
}
int kth(int k)
{
	int x = root, res;
	while (x)
	{
		if (tree[lc(x)].sz + 1 == k)
		{
			res = tree[k].lb;
			break;
		}
		if (tree[lc(x)].sz >= k)
			x = lc(x);
		else
		{
			k -= tree[lc(x)].sz;
			if (k > len(x))
			{
				k -= len(x);
				x = rc(x);
			}
			else
			{
				splitnode(x, k - 1);
				x = rc(x);
			}
		}
	}
	return res;
}
int t;
void print(int x)
{
	if (lc(x))
		print(lc(x));
	// cout << '\n';
	++t;
	for (int j = tree[x].lb; j <= tree[x].rb; ++j)
		cout << j << ' ';
	// cout << '\n';
	if (rc(x))
		print(rc(x));
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	int n, m, opt, x, y, ans = 0;
	cin >> n >> m;
	root = crt(1, n);
	for (int j = 1; j <= m; ++j)
	{
		cin >> opt >> x;
		if (opt == 1)
		{
			cin >> y;
			x -= ans, y -= ans;
			ans = update(x, y);
		}
		else if (opt == 2)
		{
			x -= ans;
			ans = tof(x);
		}
		else if (opt == 3)
		{
			x -= ans;
			ans = tol(x);
		}
		else
		{
			x -= ans;
			ans = kth(x);
		}
		cout << ans << '\n';
	}
	// cout << endl
	// 	 << endl
	// 	 //  << tree[2].lb << tree[2].rb;
	// 	 //  << (--mp.end())->first << endl;
	// 	 << mp[8];
	// cout << endl
	// 	 << mp.size()
	// 	 << endl
	// 	 << endl;
	// cout << tot << ' ';
	// print(root);
	// cout << '\n';
	// cout << t;
	// print(root);
	// for (map<int, int>::iterator it = mp.begin(); it != mp.end(); ++it)
	// {
	// 	cout << it->first << ' ' << it->second << '\n';
	// }
	// for (int j = 1; j <= tot; ++j)
	// {
	// 	cout << tree[j].lb << ' ' << tree[j].rb << '\n';
	// }
	return 0;
}

2023/2/12 23:03
加载中...