求助 zx 树,bzoj AC luogu MLE
查看原帖
求助 zx 树,bzoj AC luogu MLE
148404
sleeping_crawlers楼主2022/3/23 13:57

这是提交记录

这是代码:

#include <bits/stdc++.h>

#define maxn 100005

using namespace std;

inline int read(){
	int x = 0, flag = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9'){
		if(ch == '-') flag = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9'){
		x = (x << 3) + (x << 1) + ch - '0';
		ch = getchar();
	}
	return x * flag;
}

int cntb, n, m, q, lstans, a[maxn], b[maxn];

//---------------------一棵树
 
int cnt, hd[maxn];

struct edge{
	int v, nxt;
}e[maxn << 2];

void add(int u, int v){
	e[++cnt].v = v;
	e[cnt].nxt = hd[u];
	hd[u] = cnt;
	return;
}

//---------------------zx 树 

#define ls(x) t[x].l
#define rs(x) t[x].r

int tot, rt[maxn];

struct zxtree{
	int l, r, num;
}t[maxn * 400];

int build0(int l, int r){
	int x = ++tot;
	if(l == r) return x;
	int mid = (l + r) >> 1;
	build0(l, mid);
	build0(mid + 1, r);
	t[x].num = t[ls(x)].num + t[rs(x)].num;
	return x;
}

int build(int root, int l, int r, int k){
	int x = ++tot;
	t[x] = t[root];
	if(l == r){
		++t[x].num;
		return x;
	}
	int mid = (l + r) >> 1;
	if(k <= mid) ls(x) = build(ls(root), l, mid, k);
	else rs(x) = build(rs(root), mid + 1, r, k);
	t[x].num = t[ls(x)].num + t[rs(x)].num;
	return x;
}

int ask(int rtu, int rtv, int rtl, int rtf, int l, int r, int k){
	if(l == r) return l;
	int qwq = t[ls(rtu)].num + t[ls(rtv)].num - t[ls(rtl)].num - t[ls(rtf)].num;
	int mid = (l + r) >> 1;
	if(qwq >= k) return ask(ls(rtu), ls(rtv), ls(rtl), ls(rtf), l, mid, k);
	else return ask(rs(rtu), rs(rtv), rs(rtl), rs(rtf), mid + 1, r, k - qwq);
}

//---------------------并查集

int f[maxn], siz[maxn];

int getf(int x){
	if(f[x] == x) return x;
	return f[x] = getf(f[x]);
} 

void hb(int x, int y){
	int fx = getf(x), fy = getf(y);
	if(fx != fy){
		f[fy] = fx;
		siz[fx] += siz[fy];
	}
	return;
}

//---------------------倍增 LCA

int ff[maxn][17], dep[maxn];

void dfs(int u, int fa){
	ff[u][0] = fa;
	dep[u] = dep[fa] + 1;
	rt[u] = build(rt[fa], 1, cntb, a[u]);
	for(int i = 1; i <= 16; ++i) ff[u][i] = ff[ff[u][i - 1]][i - 1];
	for(int i = hd[u]; i; i = e[i].nxt){
		int v = e[i].v;
		if(v == fa) continue;
		dfs(v, u);
	}
	return;
}

int lca(int x, int y){
	if(dep[x] < dep[y]) swap(x, y);
	if(dep[x] != dep[y])
		for(int i = 16; i >= 0; --i)
			if(ff[x][i] && dep[ff[x][i]] >= dep[y]) x = ff[x][i];
	if(x == y) return x;
	for(int i = 16; i >= 0; --i)
		if(ff[x][i] && ff[y][i] && ff[x][i] != ff[y][i]) x = ff[x][i], y = ff[y][i];
	return ff[x][0];
}

//---------------------主函数 

int main(){
	read();
	n = read(), m = read(), q = read();
	for(int i = 1; i <= n; ++i) a[i] = b[i] = read();
	sort(b + 1, b + n + 1);
	cntb = unique(b + 1, b + n + 1) - b - 1;
	for(int i = 1; i <= n; ++i) a[i] = lower_bound(b + 1, b + cntb + 1, a[i]) - b;
	for(int i = 1; i <= n; ++i) f[i] = i, siz[i] = 1;
	while(m --> 0){
		int u = read(), v = read();
		add(u, v);
		add(v, u);
		hb(u, v);
	}
	rt[0] = build0(1, cntb);
	for(int i = 1; i <= n; ++i) if(f[i] == i) dfs(i, 0);
	while(q --> 0){
		char o;
		scanf("%c", &o);
		int x = read() ^ lstans, y = read() ^ lstans;
		if(o == 'Q'){
			int k = read() ^ lstans;
			int LCA = lca(x, y);
			lstans = b[ask(rt[x], rt[y], rt[LCA], rt[ff[LCA][0]], 1, cntb, k)];
			printf("%d\n", lstans);
		}else{
			add(x, y), add(y, x);
			if(siz[getf(x)] < siz[getf(y)]) dfs(x, y);
			else dfs(y, x);
			hb(x, y);
		}
	}
	return 0;
} 

有人帮忙看看吗 /kel

2022/3/23 13:57
加载中...