【D.都市的柏油路太硬】克鲁斯卡尔重构树的板子题,直接套板子就行了。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 5; // 点
const int M = 5e5 + 5; // 边
int n, m; // 点,边
// ==========================================================================
// 题目定义的随机数
typedef unsigned long long ull;
ull myRand(ull &k1, ull &k2) {
ull k3 = k1, k4 = k2;
k1 = k4;
k3 ^= (k3 << 23);
k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
return k2 + k4;
}
pair<int, int> myRanq(ull &k1, ull &k2, int MAXN) {
int x = myRand(k1, k2) % MAXN + 1, y = myRand(k1, k2) % MAXN + 1;
if (x > y)
return make_pair(y, x);
else
return make_pair(x, y);
}
// ==========================================================================
namespace LCA {
int dep[N], dfn[N], n;
int st[N << 1][35], lg2[35];
struct Edge {
int to, next;
} edge[N << 1];
int head[N], edge_cnt;
void init() {
edge_cnt = 0;
memset(head, -1, sizeof head);
}
void Insert(int u, int v) { // 插入邻接表
edge[++edge_cnt].to = v;
edge[edge_cnt].next = head[u];
head[u] = edge_cnt;
}
void dfs(int u, int fa) {
dfn[u] = ++n; // dfs序(欧拉序列,n'=2n-1)
dep[u] = dep[fa] + 1;
st[n][0] = u;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (v == fa) continue;
dfs(v, u);
st[++n][0] = u;
}
}
void build(int root) {
n = 0;
dfs(root, 0);
lg2[1] = 0; // log_2
for (int i = 2; i <= n; i++) lg2[i] = lg2[i >> 1] + 1;
for (int j = 1; (1 << j) <= n; j++) { // 初始化st表(Range min_dfn query)
for (int i = 1; i + (1 << j) <= n + 1; i++) {
if (dep[st[i][j - 1]] < dep[st[i + (1 << (j - 1))][j - 1]])
st[i][j] = st[i][j - 1];
else
st[i][j] = st[i + (1 << (j - 1))][j - 1];
}
}
}
int query(int u, int v) {
int lef = dfn[u], rig = dfn[v], t = lg2[abs(rig - lef) + 1];
if (lef > rig) swap(lef, rig);
if (dep[st[lef][t]] < dep[st[rig - (1 << t) + 1][t]])
return st[lef][t];
else
return st[rig - (1 << t) + 1][t];
}
}; // namespace LCA
// ==========================================================================
namespace Ex_Kruskal {
struct Edge {
int u, v;
ll w;
bool operator<(const Edge &b) const { return w < b.w; }
} edge[M];
ll fa[N], val[N];
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
void init() {
iota(fa, fa + N, 0);
LCA::init();
}
void build(int m) {
sort(edge, edge + m);
for (int i = 0; i < m; i++) {
int x = find(edge[i].u), y = find(edge[i].v);
if (x != y) {
val[++n] = edge[i].w;
fa[x] = fa[y] = n;
LCA::Insert(n, x);
LCA::Insert(n, y);
}
}
LCA::build(n);
}
int query(int u, int v) { return val[LCA::query(u, v)]; }
}; // namespace Ex_Kruskal
// ==========================================================================
// 快读
template <typename T>
inline void read(T &x) {
T f = 1;
x = 0;
char ch = getchar();
while (0 == isdigit(ch)) {
if (ch == '-') f = -1;
ch = getchar();
}
while (0 != isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
x *= f;
}
// ==========================================================================
int main() {
read(n), read(m); // 读入点数和边数
int maxn = n;
Ex_Kruskal::init(); // 初始化Ex_Kruskal
for (int i = 0; i < m; i++) { // 读入边(带权值)
read(Ex_Kruskal::edge[i].u);
read(Ex_Kruskal::edge[i].v);
read(Ex_Kruskal::edge[i].w);
}
Ex_Kruskal::build(m); // 构建Ex_Kruskal,参数(边数)
int q;
read(q);
ull ans = 0, k1, k2;
scanf("%llu%llu", &k1, &k2);
while (q--) {
pair<int, int> opt = myRanq(k1, k2, maxn);
int u = opt.first, v = opt.second;
ans ^= Ex_Kruskal::query(u, v); // 查询
}
printf("%llu", ans);
return 0;
}

京公网安备 11010502036488号