Luogu P3224 [HNOI2012]永无乡
[HNOI2012]永无乡
题目描述
永无乡包含
现在有两种操作:
B x y
表示在岛
Q x k
表示询问当前与岛
输入格式
第一行是用空格隔开的两个整数,分别表示岛的个数
第二行有
接下来
接下来一行有一个整数,表示操作个数
接下来
- 若
为Q
,则表示询问所有与岛 连通的岛中重要度排名第 小的岛是哪座,请你输出那个岛的编号。 - 若
为B
,则表示在岛 与岛 之间修建一座新桥。
输出格式
对于每个询问操作都要依次输出一行一个整数,表示所询问岛屿的编号。如果该岛屿不存在,则输出
样例 #1
样例输入 #1
5 1 4 3 2 5 1 1 2 7 Q 3 2 Q 2 1 B 2 3 B 1 5 Q 2 1 Q 2 4 Q 2 3
样例输出 #1
-1 2 5 1 2
提示
数据规模与约定
- 对于
的数据,保证 , 。 - 对于
的数据,保证 , , 为一个 的排列, , 。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define lid (tree[id].lson) #define rid (tree[id].rson) using namespace std; int n, m, q, tot, val[5211314]; int fa[5211314]; int root[5211314]; struct Segment_Tree { int lson, rson; int sum; int Rank; }tree[5211314]; inline int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch - '0'); ch = getchar(); } return x * f; } struct DisjointSetUnion { int Find(int x) { if (fa[x] == x) return x; else return fa[x] = Find(fa[x]); } bool Check(int x, int y) { if (Find(x) == Find(y)) return true; else return false; } }dsu; struct MergeSegmentTree { inline void PushUp(int id) { tree[id].sum = tree[lid].sum + tree[rid].sum; return; } void Update(int &id, int l, int r, int pos, int ans) { if (id == 0) id = ++ tot; if (l == r) { tree[id].sum = 1; tree[id].Rank = ans; return; } int mid = (l + r) >> 1; if (pos <= mid) Update(lid, l, mid, pos, ans); else Update(rid, mid + 1, r, pos, ans); PushUp(id); return; } int Merge(int a, int b, int l, int r) { if (a == 0) return b; if (b == 0) return a; if (l == r) { tree[a].sum += tree[b].sum; tree[a].Rank = tree[b].Rank; return a; } int mid = (l + r) >> 1; tree[a].lson = Merge(tree[a].lson, tree[b].lson, l, mid); tree[a].rson = Merge(tree[a].rson, tree[b].rson, mid + 1, r); PushUp(a); return a; } int Query(int id, int l, int r, int k) { int mid = (l + r) >> 1, ans; if (tree[id].sum < k || id == 0) return 0; if (l == r) return tree[id].Rank; if (k <= tree[lid].sum) ans = Query(lid, l, mid, k); else ans = Query(rid, mid + 1, r, k - tree[lid].sum); return ans; } }ask; inline void Union(int u, int v) { u = dsu.Find(u); v = dsu.Find(v); if (u == v) return; root[u] = ask.Merge(root[u], root[v], 1, n); fa[v] = u; return; } int main() { n = read(); m = read(); for (int i = 1; i <= n; ++ i) { val[i] = read(); fa[i] = i; ask.Update(root[i], 1, n, val[i], i); } for (int i = 1, u, v; i <= m; ++ i) { u = read(), v = read(); Union(u, v); } q = read(); for (int i = 1, x, y; i <= q; ++ i) { char ch = getchar(); while (ch != 'Q' && ch != 'B') { ch = getchar(); } x = read(); y = read(); if (ch == 'B') { Union(x, y); } else { x = dsu.Find(x); //注意这里一定要用find(x)的而不是fa[x]的值 //因为这里的x可能刚更新过,fa[x]的值不是合并后线段树的根节点的值 if (tree[root[x]].sum < y) printf("-1\n"); else { printf("%d\n", ask.Query(root[x], 1, n, y)); } } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具