P9638 「yyOI R1」youyou 的军训 题解
Kruskal 重构树板子。
考虑建边权从大到小排序后跑 Kruskal 的重构树,对于当前点
发现边权修改后,相对大小不变,直接在重构树点权修改即可。
倍增处理,复杂度
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <map>
using namespace std;
const int N = 8e5 + 5;
int p[N];
struct Edge
{
int u, v, w;
Edge() = default;
Edge(int u, int v, int w)
: u(u), v(v), w(w)
{
}
bool operator==(const Edge& other) const
{
return u == other.u && v == other.v && w == other.w;
}
}e[N];
int n, m, q;
int u[N], v[N], w[N];
int res[N];
int nfa[N][21];
map<pair<int, int>, int> mp;
class Union_Find
{
public:
int fa[N], idx;
int val[N], res[N];
vector<int> G[N];
void Init()
{
mp.clear();
for (int i = 0; i < N; i++) fa[i] = i, val[i] = 0, G[i].clear();
for (int i = 1; i <= n; i++) res[i] = 1;
idx = n;
}
int find(int u)
{
return (fa[u] == u ? u : fa[u] = find(fa[u]));
}
void merge(int u, int v, int w)
{
if (find(u) == find(v)) return;
mp[make_pair(u, v)] = ++idx;
u = find(u), v = find(v);
val[idx] = w;
G[idx].emplace_back(u), G[idx].emplace_back(v);
nfa[u][0] = nfa[v][0] = idx;
fa[u] = fa[v] = idx;
res[idx] += res[u] + res[v];
}
}uf;
int val[N];
vector<int> G[N];
void kruskal()
{
uf.Init();
sort(e + 1, e + m + 1, [&](const Edge& x, const Edge& y) {return x.w > y.w; });
for (int i = 1; i <= m; i++) uf.merge(e[i].u, e[i].v, e[i].w);
for (int i = 0; i < N; i++) val[i] = uf.val[i], G[i].swap(uf.G[i]);
}
int get(int u, int x)
{
for (int i = 20; i >= 0; i--)
{
if (nfa[u][i] && val[nfa[u][i]] >= x) u = nfa[u][i];
}
return u;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m >> q;
for (int i = 1; i <= m; i++)
{
cin >> u[i] >> v[i] >> w[i];
e[i] = Edge(u[i], v[i], w[i]);
}
kruskal();
for (int i = 1; i <= 20; i++)
{
for (int j = 0; j < N; j++) nfa[j][i] = nfa[nfa[j][i - 1]][i - 1];
}
for (int i = 0; i < N; i++) res[i] = uf.res[i];
int now = 0;
while (q--)
{
int op;
cin >> op;
if (op == 1)
{
cin >> now;
}
else if (op == 2)
{
int x;
cin >> x;
cout << res[get(x, now)] << "\n";
}
else
{
int x, y;
cin >> x >> y;
if (mp.count(make_pair(u[x], v[x])))
{
val[mp[make_pair(u[x], v[x])]] = y;
}
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现