Kruskal 重构树 + 倍增 + 动态开点主席树 求条
  • 板块P4197 Peaks
  • 楼主冷却心月明かり
  • 当前回复2
  • 已保存回复2
  • 发布时间2024/9/29 22:12
  • 上次更新2024/9/30 12:34:21
查看原帖
Kruskal 重构树 + 倍增 + 动态开点主席树 求条
431658
冷却心月明かり楼主2024/9/29 22:12

Record. WA 50,测试点 3,4 未过。

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int n, m, H[N];

// Kruskal Rebuild Tree
struct EDGE { int u, v, w; } e[N];
int fa[N], W[N], dfn[N], rev[N], R[N], L[N], dfncnt = 0;
vector<int> G[N];
int F[N][21];
void DFS(int u, int f) {
	F[u][0] = f;
	R[u] = -1e9, L[u] = 1e9;
	for (int v : G[u]) if (v != f) {
		DFS(v, u);
		R[u] = max(R[u], R[v]);
		L[u] = min(L[u], L[v]);
	}
	if (G[u].size() == 0) L[u] = R[u] = dfn[u] = ++ dfncnt, rev[dfn[u]] = u;
	return ;
}

int Find(int x) { if (fa[x] == x) return x; return fa[x] = Find(fa[x]); }

void Kruskal() {
	W[0] = 2e9;
	sort(e + 1, e + 1 + m, [](EDGE a, EDGE b) { return a.w < b.w; });
	for (int i = 1; i <= n * 2; i ++) fa[i] = i;
	int cnt = 0;
	for (int i = 1; i <= m; i ++) {
		int u = e[i].u, v = e[i].v, w = e[i].w;
		int fu = Find(u), fv = Find(v);
		if (fu == fv) continue;
		++ cnt;
		W[n + cnt] = w;
		fa[fu] = fa[fv] = n + cnt;
		G[n + cnt].emplace_back(fu); G[n + cnt].emplace_back(fv);
	}
	DFS(n * 2 - 1, 0);
	for (int k = 1; k <= 20; k ++) {
		for (int i = 1; i <= n * 2 - 1; i ++)
			F[i][k] = F[F[i][k - 1]][k - 1];
	}
	return ;
}
int jump(int u, int k) {
	for (int i = 20; i >= 0; i --) {
		if (W[F[u][i]] <= k)
			u = F[u][i];
	}
	return u;
}
// .
// Persistent Sgt
const int LIM = 1e9;
const int M = 5e6 + 10;
int tree[M], ls[M], rs[M], rt[N], tot = 0;
void pushup(int p) { tree[p] = tree[ls[p]] + tree[rs[p]]; }
int Copy(int p) {
	int pt = ++ tot;
	tree[pt] = p, ls[pt] = ls[p], rs[pt] = rs[p];
	return pt;
}
void update(int& p, int P, int l, int r, int x) {
	if (x > r || x < l) return ;
	p = Copy(P);
	if (l == r) { tree[p] ++; return ; }
	int mid = (l + r) >> 1;
	update(ls[p], ls[P], l, mid, x); update(rs[p], rs[P], mid + 1, r, x);
	pushup(p);
	return ;		
}
int query(int p1, int p2, int l, int r, int k) {
	if (l == r) { return (k <= tree[p2] - tree[p1] ? l : -1); }
	int d = tree[rs[p2]] - tree[rs[p1]], mid = (l + r) >> 1;
	if (k <= d) return query(rs[p1], rs[p2], mid + 1, r, k);
	return query(ls[p1], ls[p2], l, mid, k - d);
}
//.
int main() {
	ios :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int Q;
	cin >> n >> m >> Q;
	for (int i = 1; i <= n; i ++) cin >> H[i];
	for (int i = 1, u, v, w; i <= m; i ++) {
		cin >> u >> v >> w; e[i] = {u, v, w};
	}
	Kruskal(); 
	for (int i = 1; i <= n; i ++) {
		update(rt[i], rt[i - 1], 1, LIM, H[rev[i]]);
	}
	int x, y, w;
	while (Q --) {
		cin >> x >> y >> w;
		int t = jump(x, y), l = L[t], r = R[t];
		cout << query(rt[l - 1], rt[r], 1, LIM, w) << "\n";
	}
	return 0;
}
2024/9/29 22:12
加载中...