[HNOI2012]永无乡
P3224 [HNOI2012]永无乡
因为要维护联通的状态,所以我们可以使用并查集维护联通状态,然后跑线段树合并(不会的可以看这个)。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int fa[N] , ps , n , flag[N];
char c;
struct Tr {
int v , l , r;
}tr[10000005];
int find(int x) {
if(fa[x] == x)
return x;
else
return fa[x] = find(fa[x]);
}
void updata(int p) {
tr[p].v = tr[tr[p].l].v + tr[tr[p].r].v;
}
void get_l(int p) {
if(!tr[p].l)
tr[p].l = ++ps;
}
void get_r(int p) {
if(!tr[p].r)
tr[p].r = ++ps;
}
void change(int p , int l , int r , int pos , int val) {
if(l == r) {
tr[p].v += val;
}
else {
int mid = l + r >> 1;
if(pos <= mid) {
get_l(p);
change(tr[p].l , l , mid , pos , val);
}
else {
get_r(p);
change(tr[p].r , mid + 1 , r , pos , val);
}
updata(p);
}
}
int query(int p , int l , int r , int k) {
if(l == r) {
return l;
}
else {
int mid = l + r >> 1;
if(tr[tr[p].l].v + tr[tr[p].r].v < k )
return -1;
if(tr[tr[p].l].v >= k) {
return query(tr[p].l , l , mid , k);
}
else {
return query(tr[p].r , mid + 1 , r , k - tr[tr[p].l].v);
}
}
}
void Marge(int x , int y ,int l , int r) {
if(l==r) {
tr[x].v += tr[y].v;
}
else {
int mid = l + r >> 1;
if(!tr[x].l && tr[y].l) {
tr[x].l = tr[y].l;
}
else if(tr[x].l && tr[y].l) {
Marge(tr[x].l , tr[y].l , l , mid);
}
if(!tr[x].r && tr[y].r) {
tr[x].r = tr[y].r;
}
else if(tr[x].r && tr[y].r) {
Marge(tr[x].r , tr[y].r , mid + 1 , r);
}
updata(x);
}
}
void chan(int x , int y) {
int fa1 = find(x) , fa2 = find(y);
fa[fa2] = fa1;
Marge(fa1 , fa2 , 1 , n);
}
int main() {
int m , u , v , a , q , ans;
scanf("%d%d" , &n , &m);
ps = n;
for(int i = 1 ; i <= n ; i++) {
scanf("%d" , &a);
change(i , 1 , n , a , 1);
fa[i] = i;
flag[a] = i;
}
for(int i = 1 ; i <= m ; i++) {
scanf("%d%d" , &u , &v);
chan(u , v);
}
scanf("%d",&q);
while(q--) {
c = getchar();
while(c != 'Q' && c != 'B')
c = getchar();
if(c == 'B') {
scanf("%d%d" , &u , &v);
chan(u , v);
}
else {
scanf("%d%d" , &u , &v);
ans = query(find(u) , 1 , n , v);
if(ans == -1)
printf("-1\n");
else
printf("%d\n" , flag[ans]);
}
}
return 0;
}
如果人生会有很长,愿有你的荣耀永不散场