luogu P5064 [Ynoi2014] 等这场战争结束之后

#include<bits/stdc++.h>
#define N 100005
using namespace std;
struct edge {
    int v, nxt;
} e[N];
int p[N], eid;
void init() {
    memset(p, -1, sizeof p);
    eid = 0;
}
void insert(int u, int v) {
    e[eid].v = v;
    e[eid].nxt = p[u];
    p[u] = eid ++;
}
struct A {
    int x, y;
} a[N];
int cmp(A x, A y) {
    return x.x < y.x;
}
short cnt[N][36];
int n, m, X[N], Y[N], O[N], size[N], fa[N], K, blo, ans[N];
int get(int x) { return x == fa[x]? x : get(fa[x]); }
void dfs(int u) {
    int f = 0;
    int o = O[u], &x = X[u], &y = Y[u];
    if(o == 1) {
        x = get(x), y = get(y);
        if(x != y) {
            f = 1;
            if(size[x] > size[y]) swap(x, y);
            fa[x] = y; size[y] += size[x];
            for(int i = 1; i <= K; i ++) cnt[y][i] += cnt[x][i];
        }
    } else if(o == 3) {
        x = get(x);
        if(y > size[x]) ans[u] = -1;
        else {
            int id = 0;
            for(int i = 1; i <= K; i ++) {
                if(y > cnt[x][i]) y -= cnt[x][i];
                else {
                    id = i;
                    break;
                }
            }
            for(int i = (id - 1) * blo + 1; i <= min(id * blo, n); i ++) {
                if(get(a[i].y) == x) y --, ans[u] = a[i].x;
                if(!y) break;
            }
        }
    }
    
    for(int i = p[u]; i + 1; i = e[i].nxt) dfs(e[i].v);
    if(f) {
        for(int i = 1; i <= K; i ++) cnt[y][i] -= cnt[x][i];
        fa[x] = x, size[y] -= size[x];
    }
}
int main() {
    init();
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i].x), a[i].y = i;
    sort(a + 1, a + 1 + n, cmp);
    K = 35; blo = n / K + 1; K = (n - 1) / blo + 1;
    for(int i = 1; i <= n; i ++) {
        int bel = (i - 1) / blo + 1;
        cnt[a[i].y][bel] ++;
        size[i] = 1; fa[i] = i;
    }
    for(int i = 1; i <= m; i ++) {
        scanf("%d", &O[i]);
        if(O[i] == 1) {
            scanf("%d%d", &X[i], &Y[i]);
            insert(i - 1, i);
        }
        else if(O[i] == 2) {
            scanf("%d", &X[i]);
            insert(X[i], i);
        } else {
            scanf("%d%d", &X[i], &Y[i]);
            insert(i - 1, i);
        }
    }
    dfs(0);
    for(int i = 1; i <= m; i ++) if(O[i] == 3) printf("%d\n", ans[i]);
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值