[HNOI2012]永无乡
日了狗了,原来启发式合并是个暴力,我真是见鬼了,直接把size小的平衡树暴力插进去,我以为是啥高级算法。
//author Eterna #define Hello the_cruel_world! #pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cstdio> #include<string> #include<cstring> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<utility> #include<cmath> #include<climits> #include<deque> #include<functional> #include<complex> #include<numeric> #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)<(y)?(x):(y)) #define Pi acos(-1.0) #define ABS(x) ((x) >= 0 ? (x) : (-(x))) #define pb(x) push_back(x) #define lowbit(x) (x & -x) #define FRIN freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\in.txt", "r", stdin) #define FROUT freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\out.txt", "w", stdout) #define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #define ls(x) arr[x].child[0] #define rs(x) arr[x].child[1] #define out(x) printf("%d\n", x) using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int maxn = 1e5; const int INF = 0x7fffffff; const int mod = 19260817; const double eps = 1e-7; inline int read_int() { char c; int ret = 0, sgn = 1; do { c = getchar(); } while ((c < '0' || c > '9') && c != '-'); if (c == '-') sgn = -1; else ret = c - '0'; while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0'); return sgn * ret; } inline ll read_ll() { char c; ll ret = 0, sgn = 1; do { c = getchar(); } while ((c < '0' || c > '9') && c != '-'); if (c == '-') sgn = -1; else ret = c - '0'; while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0'); return sgn * ret; } struct node{ int child[2], value, key, size; }arr[20 * maxn + 5]; int tot; inline void Push_Up(int index){ arr[index].size = arr[ls(index)].size + arr[rs(index)].size + 1; } void Split(int root, int& x, int& y, int value){ if(!root){ x = y = 0; return; } if(arr[root].value <= value)x = root, Split(rs(root), rs(x), y, value); else y = root, Split(ls(root), x, ls(y), value); Push_Up(root); } void Merge(int& root, int x, int y){ if(!x || !y){ root = x + y; return; } if(arr[x].key < arr[y].key)root = x, Merge(rs(root), rs(x), y); else root = y, Merge(ls(root), x, ls(y)); Push_Up(root); } inline void Insert(int& root, int value){ int x = 0, y = 0, z = ++tot; arr[z].value = value, arr[z].size = 1, arr[z].key = rand(); Split(root, x, y, value); Merge(x, x, z); Merge(root, x, y); } inline int kth_number(int root, int k){ while(arr[ls(root)].size + 1 != k){ if(arr[ls(root)].size >= k)root = ls(root); else k -= (arr[ls(root)].size + 1), root = rs(root); } return arr[root].value; } void DFS(int now, int& root){ if(now)Insert(root, arr[now].value); if(ls(now))DFS(ls(now), root); if(rs(now))DFS(rs(now), root); } int ufs[maxn + 5], root[maxn + 5], Rank[maxn + 5]; inline int find(int x){ return x == ufs[x] ? x : ufs[x] = find(ufs[x]); } void unite(int x, int y){ x = find(x), y = find(y); if(x != y){ if(arr[root[x]].size > arr[root[y]].size)swap(x, y); DFS(root[x], root[y]); ufs[x] = y; } } int n, m, q; char op; int main() { n = read_int(), m = read_int(); for(int i = 1; i <= n; ++i){ ufs[i] = i; int x = read_int(); Rank[x] = i; Insert(root[i], x); } while(m--){ int x = read_int(), y = read_int(); unite(x, y); } q = read_int(); while(q--){ scanf(" %c", &op); if(op == 'Q'){ int x = read_int(), k = read_int(); x = find(x); if(arr[root[x]].size < k)out(-1); else { int m = kth_number(root[x], k); out(Rank[m]); } } else { int x = read_int(), y = read_int(); unite(x, y); } } return 0; }
posted on 2019-03-19 20:47 Eterna_King 阅读(122) 评论(0) 编辑 收藏 举报