Description
永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。
Input
输入文件第一行是用空格隔开的两个正整数 n 和 m,分别 表示岛的个数以及一开始存在的桥数。接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。随后的 m 行每行是用空格隔开的两个正整数 ai 和 bi,表示一开始就存 在一座连接岛 ai 和岛 bi 的桥。后面剩下的部分描述操作,该部分的第一行是一个正整数 q, 表示一共有 q 个操作,接下来的 q 行依次描述每个操作,操作的格式如上所述,以大写字母 Q 或B 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。 对于 20%的数据 n≤1000,q≤1000
对于 100%的数据 n≤100000,m≤n,q≤300000
Output
对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表 示所询问岛屿的编号。如果该岛屿不存在,则输出-1。
Sample Input
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
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
Sample Output
-1
2
5
1
2
2
5
1
2
题解
之前写了个$splay$一直错的没改过来...
最近喻队让我用线段树合并写这道题,嗯...不错,样例调对了$1A$。
指针党表示这种动态存储的数据结构都直接上指针...
1 //It is made by Awson on 2017.10.20 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <stack> 7 #include <queue> 8 #include <vector> 9 #include <string> 10 #include <cstdio> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define Min(a, b) ((a) < (b) ? (a) : (b)) 17 #define Max(a, b) ((a) > (b) ? (a) : (b)) 18 #define Abs(x) ((x) < 0 ? (-(x)) : (x)) 19 using namespace std; 20 const int N = 100000; 21 22 int n, m, a, b; 23 char opt[10]; 24 int val[N+5], id[N+5]; 25 struct node { 26 int key; 27 node* child[2]; 28 }sgm[N*20], *root[N+5], *pos = sgm; 29 struct segment { 30 void insert(node* &o, int l, int r, int loc) { 31 if (o == NULL) o = pos++; 32 if (l == r) { 33 o->key = 1; return; 34 } 35 int mid = (l+r)>>1; 36 if (loc <= mid) insert(o->child[0], l, mid, loc); 37 else insert(o->child[1], mid+1, r, loc); 38 o->key = 0; 39 if (o->child[0]) o->key += o->child[0]->key; 40 if (o->child[1]) o->key += o->child[1]->key; 41 } 42 node* merge(node* a, node* b) { 43 if (!b || !a) return a ? a : b; 44 a->child[0] = merge(a->child[0], b->child[0]); 45 a->child[1] = merge(a->child[1], b->child[1]); 46 a->key = 0; 47 if (a->child[0]) a->key += a->child[0]->key; 48 if (a->child[1]) a->key += a->child[1]->key; 49 return a; 50 } 51 int query(node* o, int l, int r, int kth) { 52 if (l == r) return l; 53 int mid = (l+r)>>1; 54 if (!o->child[0]) return query(o->child[1], mid+1, r, kth); 55 if (o->child[0]->key >= kth) return query(o->child[0], l, mid, kth); 56 return query(o->child[1], mid+1, r, kth-o->child[0]->key); 57 } 58 }T; 59 int fa[N+5]; 60 int find(int r) { 61 return fa[r] ? fa[r] = find(fa[r]) : r; 62 } 63 64 void work() { 65 scanf("%d%d", &n, &m); 66 for (int i = 1; i <= n; i++) { 67 scanf("%d", &val[i]); id[val[i]] = i; 68 } 69 for (int i = 1; i <= n; i++) T.insert(root[i], 1, n, val[i]); 70 while (m--) { 71 scanf("%d%d", &a, &b); 72 int q = find(a), p = find(b); 73 if (p != q) { 74 root[q] = T.merge(root[p], root[q]); 75 fa[p] = q; 76 } 77 } 78 scanf("%d", &m); 79 while (m--) { 80 scanf("%s%d%d", &opt, &a, &b); 81 if (opt[0] == 'B') { 82 int q = find(a), p = find(b); 83 if (p != q) { 84 root[q] = T.merge(root[p], root[q]); 85 fa[p] = q; 86 } 87 }else { 88 int q = find(a); 89 if (b > root[q]->key) printf("-1 "); 90 else printf("%d ", id[T.query(root[q], 1, n, b)]); 91 } 92 } 93 } 94 int main() { 95 work(); 96 return 0; 97 }