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
用Treap维护并询问第K大,并查集维护在哪颗Treap上,合并时数量小的暴力加到数量大的中。
Tips:最好不要再结构体构造函数中初始化priority值,因为用了并查集维护,我们要保证根节点的priority最小,使得fa数组一定指向Treap的根。
/**************************************************************
Problem: 2733
User: cabinfever
Language: C++
Result: Accepted
Time:1964 ms
Memory:3636 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <iostream>
using namespace std;
#define N 100010
int n,m,q;
struct node
{
int l,r,priority,size,key;
node()
{
size = 1;
priority = l = r = 0;
}
}a[N];
int fa[N];
int getfa(int x)
{
if(x == fa[x])
return x;
fa[x] = getfa(fa[x]);
return fa[x];
}
void rotate_right(int &x)
{
int temp = a[x].l;
a[x].l = a[temp].r;
a[temp].r = x;
a[temp].size = a[x].size;
a[x].size = a[a[x].l].size + 1 + a[a[x].r].size;
x = temp;
}
void rotate_left(int &x)
{
int temp = a[x].r;
a[x].r = a[temp].l;
a[temp].l = x;
a[temp].size = a[x].size;
a[x].size = a[a[x].l].size + 1 + a[a[x].r].size;
x = temp;
}
void insert(int &x,int t)
{
if(x)
{
a[x].size++;
if(a[t].key < a[x].key)
{
insert(a[x].l,t);
if(a[a[x].l].priority < a[x].priority)
rotate_right(x);
}
else
{
insert(a[x].r,t);
if(a[a[x].r].priority < a[x].priority)
rotate_left(x);
}
}
else
{
x = t;
a[t].priority = rand();
}
}
void merge_node(int x,int y)
{
if(!y)
return;
merge_node(x,a[y].l);
merge_node(x,a[y].r);
insert(x,y);
}
void merge(int u,int v)
{
int fa_u = getfa(u);
int fa_v = getfa(v);
if(fa_u == fa_v)
return;
if(a[fa_u].size < a[fa_v].size)
swap(fa_u,fa_v);
fa[fa_v] = fa_u;
merge_node(fa_u,fa_v);
}
int get_Kth(int x,int k)
{
if(k <= a[a[x].l].size)
return get_Kth(a[x].l,k);
k -= a[a[x].l].size + 1;
if(k == 0)
return x;
return get_Kth(a[x].r,k);
}
int main()
{
a[0].size = 0;
cin >> n >> m;
for(int i = 1; i <= n; i++)
scanf("%d",&a[i].key);
for(int i = 1; i <= n; i++)
fa[i] = i;
for(int i = 1; i <= m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
merge(u,v);
}
cin >> q;
char c;
for(int i = 1; i <= q; i++)
{
scanf(" %c",&c);
if(c == 'B')
{
int u,v;
scanf("%d%d",&u,&v);
merge(u,v);
}
else
{
int x,k;
scanf("%d%d",&x,&k);
x = getfa(x);
if(a[x].size < k)
printf("-1\n");
else
printf("%d\n",get_Kth(x,k));
}
}
return 0;
}