您的位置:首页 > 其它

BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)

2015-04-30 23:37 681 查看


不难...treap + 启发式合并 + 并查集 搞搞就行了

----------------------------------------------------------------------------------------

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream> #define rep(i, n) for(int i = 0; i < n; ++i)#define clr(x, c) memset(x, c, sizeof(x)) using namespace std; const int maxn = 100000 + 5; int p[maxn]; struct node *null, *pt;struct node { node* ch[2]; int v, s, r, x; node(int _v = 0, int _x = 0) : v(_v), x(_x), s(1), r(rand()) { ch[0] = ch[1] = null; } inline int cmp(int _v) { if(v == _v) return -1; return _v < v ? 0 : 1; } inline void maintain() { s = ch[0]->s + ch[1]->s + 1; } void* operator new (size_t) { return pt++; }}; node* root[maxn], N[maxn * 30]; void rotate(node* &o, int d) { node* k = o->ch[d ^ 1]; o->ch[d ^ 1] = k->ch[d]; k->ch[d] = o; o->maintain(); k->maintain(); o = k; } int x, v;void insert(node* &o) { if(o == null) o = new node(v, x); else { int d = v < o->v ? 0 : 1; insert(o->ch[d]); if(o->ch[d]->r > o->r) rotate(o, d ^ 1); } o->maintain();} void merge(node* &o, node* &O) { if(o == null) return; rep(i, 2) merge(o->ch[i], O); x = o->x; v = o->v; insert(O);} int kth(node* o, int k) { int s = o->ch[0]->s; if(k == s + 1) return o->x; return k <= s ? kth(o->ch[0], k) : kth(o->ch[1], k - s - 1);} int find(int x) { return x == p[x] ? x : p[x] = find(p[x]); } void init(int n) { pt = N; null = new(node); rep(i, n) root[p[i] = i] = null; null->s = 0;} void B(int u, int v) { int x = find(u), y = find(v); if(x != y) { if(root[x]->s > root[y]->s) swap(x, y); p[x] = y; merge(root[x], root[y]); }} int query(int x, int k) { int X = find(x); if(k > root[X]->s) return -1; return kth(root[X], k);} int main() { int n, m; scanf("%d%d", &n, &m); init(n); rep(i, n) { x = i + 1; scanf("%d", &v); insert(root[i]); } while(m--) { int u, v; scanf("%d%d", &u, &v); B(u - 1, v - 1); } scanf("%d", &m); while(m--) { int u, v; char op; scanf(" %c%d%d", &op, &u, &v); if(op == 'B') B(u - 1, v - 1); else printf("%d\n", query(u - 1, v)); } return 0;}----------------------------------------------------------------------------------------

2733: [HNOI2012]永无乡

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1455 Solved: 771
[Submit][Status][Discuss]

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

Sample Output

-1
2
5
1
2

HINT

Source

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: