社区讨论

求助dalao!本地跑的贼快,交上去全T

P2617Dynamic Rankings参与者 4已保存回复 8

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
8 条
当前快照
1 份
快照标识符
@loct53rh
此快照首次捕获于
2023/10/30 19:19
2 年前
此快照最后确认于
2023/11/05 05:59
2 年前
查看原帖
RT
CPP
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 2e6 + 10;
int n, m, a[N], root[N << 2];
struct FHQ_Treap {
	int tot = 0;
	struct node {
		int l, r;
		int siz, key, val;
	}tr[N];
	FHQ_Treap () {
		tot = 0;
		memset (tr, 0, sizeof (tr));
	}
	
	int newnode (int v) {
		tr[++tot].key = rand();
		tr[tot].siz = 1; tr[tot].val = v;
		return tot;
	}
	
	int pushup (int k) {
		tr[k].siz = tr[tr[k].l].siz + tr[tr[k].r].siz + 1;
	}
	
	void split (int nd, int k, int &x, int &y) {
		if (!nd) x = y = 0;
		else {
			if (tr[nd].val <= k) {
				x = nd;
				split (tr[x].r, k, tr[x].r, y);
			}
			else {
				y = nd;
				split (tr[y].l, k, x, tr[y].l);
			}
			pushup (nd);
		}
	}
	
	void merge (int &root, int x, int y) {
		if (!x || !y) { root = x + y; return ; }
		if (tr[x].key < tr[y].key) {
			root = x;
			merge (tr[root].r, tr[x].r, y);
			pushup (x);
		}
		else {
			root = y;
			merge (tr[root].l, x, tr[y].l);
			pushup (y);
		}
	}
	
	void ins (int &root, int k) {
		int x, y, z = newnode (k);
		split (root, k, x, y);
		merge (x, x, z); merge (root, x, y);
	}
	
	void del (int &root, int k) {
		int x, y, c, d;
		split (root, k, x, y);
		split (x, k - 1, c, d);
		merge (d, tr[d].l, tr[d].r);
		merge (c, c, d); merge (root, c, y);
	}
	
	int rank (int &root, int k) {
		int x, y, s = 0;
		split (root, k - 1, x, y);
		s = tr[x].siz + 1;
		merge (root, x, y);
		return s;
	}
}F;

void change (int nd, int l, int r, int x, int ov, int nv) {
	F.del(root[nd], ov); F.ins(root[nd], nv);
	if (l == r) return ;
	int mid = l + r >> 1;
	if (x <= mid) change (nd<<1, l, mid, x, ov, nv);
	else change (nd<<1|1, mid + 1, r, x, ov, nv);
}

int getrank (int nd, int l, int r, int x, int y, int k) {
	if (l == x && r == y) return F.rank(root[nd], k) - 1;
	int mid = l + r >> 1;
	if (y <= mid) return getrank (nd<<1, l, mid, x, y, k);
	if (x > mid) return getrank (nd<<1|1, mid + 1, r, x, y, k);
	return getrank (nd<<1, l, mid, x, mid, k) + getrank (nd<<1|1, mid + 1, r, mid + 1, y, k);
}

int findval (int l, int r, int k) {
	int lb = 0, rb = (int)(1e9), mid, tmp1, tmp2;
	while (lb <= rb) {
		mid = lb + rb >> 1;
		tmp1 = getrank (1, 1, n, l, r, mid);
		tmp2 = getrank (1, 1, n, l, r, mid + 1);
		if (tmp1 < k && tmp2 >= k) return mid;
		if (tmp1 >= k) rb = mid - 1;
		else lb = mid + 1;
	}
}

int main () {
	scanf ("%d%d", &n, &m);
	for (int i = 1; i <= n; i ++ ) {
		scanf ("%d", &a[i]);
		change (1, 1, n, i, 0, a[i]);
	}
//	for (int i = 1; i <= n * 2; i ++ ) cout << root[i] << " ";
//	cout << endl;
	for (int i = 1; i <= m; i ++ ) {
		char opt; int x, y, k;
		cin >> opt;
		scanf ("%d%d", &x, &y);
		switch (opt) {
			case 'C': change (1, 1, n, x, a[x], y); a[x] = y; break;
			case 'Q': scanf ("%d", &k); printf ("%d\n", findval (x, y, k)); break;
		}
	}
	return 0;
}

回复

8 条回复,欢迎继续交流。

正在加载回复...