萌新求助 永无乡TLE on#10 90pts
查看原帖
萌新求助 永无乡TLE on#10 90pts
308796
LoserKugua楼主2022/12/5 17:04

卡常卡了半天了,其他的点跑得都快比有些已经AC的提交快了,就#10甚至过不了,萌新用的fhq_treap+启发式合并,求助

// 想法一开始是对的,暴力启发式合并+并查集维护就可以了
// 然后以为可以直接logn像fhq_treap那样合并,其实不行,很容易hack掉 
#include<cstdio>
#include<random>
#include<ctime>
#include<iostream>
using namespace std;
const int maxn = 100005;
int im[maxn],fa[maxn],rt[maxn],n,m,q,x,y,ui,vi;// rt为真实的结点编号 
char op;
int getfa(int x) {// 并查集找根 
	int temp = x;
	while(temp != fa[temp]) temp = fa[temp];
	return fa[x] = temp;
}
// fhq_treap
mt19937 rnd(time(0));
int ls[maxn],rs[maxn],size[maxn],wei[maxn],tot;
void split(int p, int v, int &x, int &y) {
	if(!p) {x = 0; y = 0; return;}
	if(im[p] <= v) {x = p; split(rs[p], v, rs[p], y);}
	else {y = p; split(ls[p], v, x, ls[p]);}
	size[p] = size[ls[p]] + size[rs[p]] + 1;
}
int Merge(int x, int y) {
	if(!x || !y) return x + y;
	if(wei[x] < wei[y]) {
		rs[x] = Merge(rs[x], y);
		size[x] = size[ls[x]] + size[rs[x]] + 1;
		return x;
	} 
	else {
		ls[y] = Merge(x, ls[y]);
		size[y] = size[ls[y]] + size[rs[y]] + 1;
		return y;
	}
}
int Find(int p, int kth) {
	while(kth != size[ls[p]] + 1) {
		if(kth <= size[ls[p]]) p = ls[p];
		else {
			kth -= size[ls[p]] + 1;
			p = rs[p];
		}		
	}
	return p;
}
void dfs_merge(int &root, int p) {// 启发式合并 p合并到root内 一个点一个点地抽出来 
	int l = ls[p], r = rs[p]; ls[p] = rs[p] = 0;
	size[p] = 1;
	if(l) dfs_merge(root, l);
	int x,y;
	split(root, im[p] - 1, x, y);
	root = Merge(Merge(x, p), y);
	if(r) dfs_merge(root, r);
}
void qfs_merge(int x, int y) {// 启发式合并 
	if(size[rt[x]] < size[rt[y]]) {
		dfs_merge(rt[y], rt[x]);
		fa[x] = y;
	}
	else {
		dfs_merge(rt[x], rt[y]);
		fa[y] = x;
	}
}
int ffread() {
	int ret = 0;
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9') {
		ret = (ret << 1) + (ret << 3) + c - 48;
		c = getchar();
	}
	return ret;
}
void ffout(int x) {
	short sta[13], top = 0;
	do {
		sta[top++] = x % 10;
		x /= 10;
	}while(x);
	while(top) putchar(sta[--top] + 48);
}
int main() {
	// 输入输出有问题。。。服了
	n = ffread(); m = ffread();
	for(int i = 1; i <= n; ++i) {
		im[i] = ffread(); fa[i] = i;
		size[i] = 1; wei[i] = rnd();
		rt[i] = i;
	}
	for(int i = 1; i <= m; ++i) {
		ui = ffread(); vi = ffread();
		qfs_merge(getfa(ui), getfa(vi));
	}
	q = ffread();
	for(int i = 1; i <= q; ++i) {
		scanf("\n%c", &op);// \n可以解决 
		x = ffread(); y = ffread();
		if(op == 'B') {
			if(getfa(x) == getfa(y)) continue;// 已经合并
			qfs_merge(fa[x], fa[y]);
		}
		else {
			if(size[rt[fa[x]]] < y) {// 不存在这样的点 
				putchar('-');
				putchar('1');
				putchar('\n');
			}
			else {
				ffout(Find(rt[fa[x]], y));
				putchar('\n');
			}
		}
	}
	return 0;
}
2022/12/5 17:04
加载中...