[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;
}
posted @ 2023-03-22 19:52  2020fengziyang  阅读(25)  评论(0编辑  收藏  举报