1. 程式人生 > >[HNOI 2012] 永無鄉

[HNOI 2012] 永無鄉

[題目連結]

         https://www.lydsy.com/JudgeOnline/problem.php?id=2733

[演算法]

        用線段樹維護圖的聯通塊 , 並查集維護連通性

        加邊時可以直接線段樹合併

        時間複雜度 : O(NlogN)

[程式碼]

        

#include<bits/stdc++.h>
using
namespace std; #define MAXN 100010 #define MAXP 10000010 typedef long long ll; typedef long double ld; typedef unsigned long long ull; int n , m; int fa[MAXN] , rt[MAXN] , rk[MAXN] , rev[MAXN]; struct Segment_Tree { int sz; Segment_Tree() { sz = 0; }
struct Node { int cnt; int lc , rc; } a[MAXP]; inline int merge(int x , int y) { if (x == 0 || y == 0) return x + y; a[x].cnt += a[y].cnt; a[x].lc = merge(a[x].lc , a[y].lc); a[x].rc
= merge(a[x].rc , a[y].rc); return x; } inline void update(int x) { a[x].cnt = a[a[x].lc].cnt + a[a[x].rc].cnt; } inline void modify(int &now , int l , int r , int x , int value) { if (!now) now = ++sz; if (l == r) { a[now].cnt = 1; return; } int mid = (l + r) >> 1; if (mid >= x) modify(a[now].lc , l , mid , x , value); else modify(a[now].rc , mid + 1 , r , x , value); update(now); } inline int query(int &now , int l , int r , int k) { if (!now) now = ++sz; if (l == r) return l; int mid = (l + r) >> 1; if (a[a[now].lc].cnt >= k) return query(a[now].lc , l , mid , k); else return query(a[now].rc , mid + 1 , r , k - a[a[now].lc].cnt); } inline int query(int now , int k) { if (a[rt[now]].cnt < k) return -1; else return query(rt[now] , 1 , n , k); } } SGT; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline int get_root(int x) { if (fa[x] == x) return x; else return fa[x] = get_root(fa[x]); } int main() { scanf("%d%d" , &n , &m); for (int i = 1; i <= n; i++) { scanf("%d" , &rk[i]); rev[rk[i]] = i; } for (int i = 1; i <= n; i++) { fa[i] = i; rt[i] = 0; } for (int i = 1; i <= n; i++) SGT.modify(rt[i] , 1 , n , rk[i] , 1); for (int i = 1; i <= m; i++) { int x , y; scanf("%d%d" , &x , &y); if (get_root(x) != get_root(y)) { rt[get_root(y)] = SGT.merge(rt[get_root(x)] , rt[get_root(y)]); fa[get_root(x)] = get_root(y); } } int q; scanf("%d" , &q); while (q--) { char type[5]; scanf("%s" , type); if (type[0] == 'Q') { int x , k; scanf("%d%d" , &x , &k); int tmp = SGT.query(get_root(x) , k); if (tmp == -1) printf("-1\n"); else printf("%d\n" , rev[tmp]); } else { int x , y; scanf("%d%d" , &x , &y); if (get_root(x) != get_root(y)) { rt[get_root(y)] = SGT.merge(rt[get_root(x)] , rt[get_root(y)]); fa[get_root(x)] = get_root(y); } } } return 0; }