• [SDOI2013]森林 (启发式合并)


    /*
    树上主席树能够求出链上第k大, 然后启发式合并直接重构就好了
    卡常数就卡呗
    反正我就暴力重构了!!
    
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<iostream>
    #define ll long long
    #define mmp make_pair
    #define M 100010
    using namespace std;
    int read() {
    	int nm = 0, f = 1;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm * f;
    }
    int fa[M][17], sz[M], rt[M], belong[M], n, m, T, cnt, a[M], b[M], deep[M], ans;
    int t[M * 17 * 17], ls[M * 17 * 17], rs[M * 17 * 17];
    vector<int> to[M];
    char s[M];
    
    void modify(int l, int r, int last, int &now, int v) {
    	now = ++cnt;
    	t[now] = t[last] + 1;
    	ls[now] = ls[last];
    	rs[now] = rs[last];
    	if(l == r) return;
    	int mid = (l + r) >> 1;
    	if(v <= mid) modify(l, mid, ls[last], ls[now], v);
    	else modify(mid + 1, r, rs[last], rs[now], v);
    }
    
    void dfs(int now, int f, int zu) {
    	belong[now] = zu;
    	deep[now] = deep[f] + 1;
    	modify(1, n, rt[f], rt[now], a[now]);
    	fa[now][0] = f;
    	for(int i = 1; i <= 16; i++) fa[now][i] = fa[fa[now][i - 1]][i - 1];
    	for(int i = 0; i < to[now].size(); i++) {
    		int vj = to[now][i];
    		if(vj == f) continue;
    		dfs(vj, now, zu);
    	}
    }
    
    int lca(int a, int b) {
    	if(deep[a] < deep[b]) swap(a, b);
    	int dep = deep[a] - deep[b];
    	for(int i = 0; dep; i++, dep >>= 1) if(dep & 1) a = fa[a][i];
    	if(a == b) return a;
    	for(int i = 16; i >= 0; i--) {
    		if(fa[a][i] == fa[b][i]) continue;
    		a = fa[a][i], b = fa[b][i];
    	}
    	return fa[a][0];
    }
    
    int query(int l, int r, int rt1, int rt2, int rt3, int rt4, int k) {
    	if(l == r) return l;
    	int mid = (l + r) >> 1;
    	int v = t[ls[rt4]] + t[ls[rt3]] - t[ls[rt2]] - t[ls[rt1]];
    	if(k <= v) return query(l, mid, ls[rt1], ls[rt2], ls[rt3], ls[rt4], k);
    	else return query(mid + 1, r, rs[rt1], rs[rt2], rs[rt3], rs[rt4], k - v);
    }
    
    int main() {
    	read();
    	n = read(), m = read(), T = read();
    	for(int i = 1; i <= n; i++) a[i] = b[i] = read();
    	sort(b + 1, b + n + 1);
    	for(int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
    	for(int i = 1; i <= m; i++) {
    		int vi = read(), vj = read();
    		to[vi].push_back(vj);
    		to[vj].push_back(vi);
    	}
    	for(int i = 1; i <= n; i++) {
    		if(!belong[i]) dfs(i, 0, i);
    	}
    	for(int i = 1; i <= n; i++) sz[belong[i]]++;
    	while(T--) {
    		scanf("%s", s + 1);
    		if(s[1] == 'Q') {
    			int vi = read() ^ ans, vj = read() ^ ans, k = read() ^ ans;
    			int l = lca(vi, vj);
    			ans = b[query(1, n, rt[l], rt[fa[l][0]], rt[vi], rt[vj], k)];
    			cout << ans << "
    ";
    		} else {
    			int vi = read() ^ ans, vj = read() ^ ans;
    			if(sz[belong[vi]] > sz[belong[vj]]) swap(vi, vj);
    			sz[belong[vj]] += sz[belong[vi]];
    			sz[belong[vi]] = 0;
    			dfs(vi, vj, belong[vj]);
    			to[vi].push_back(vj);
    			to[vj].push_back(vi);
    		}
    	}
    	return 0;
    }
    /*
    10 
    5 0 5
    1 2 3 4 5
    L 1 2
    L 2 3
    L 1 5
    L 4 5
    Q 3 4 1
    */
    
  • 相关阅读:
    使用koa+mongodb构建的仿知乎接口(二)
    使用koa+mongodb构建的仿知乎接口(一)
    flask学习笔记
    后端遇到一些问题
    前端项目一些细节总结
    python基础学习
    vue本地运行项目使用iframe的跨域问题
    hover状态下改变图片颜色的方式 悬停图片切换;css变量;悬停svg图片改变颜色;VUE
    深拷贝
    git初使用
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/10722815.html
Copyright © 2020-2023  润新知