线段树合并的小方法

线段树合并

1、例题:P3324

struct node{
    int siz, id, l, r;
    node(int siz = 0, int id = 0, int l = 0, int r = 0) : siz(siz), id(id), l(l), r(r) {}
} tree[N + 1];
int tot;
int rt[N + 1];

void push_up(int root) {
    auto &ls = tree[root].l, &rs = tree[root].r;
    tree[root].siz = tree[ls].siz + tree[rs].siz;
}

void ins(int &nw, int l, int r, int pos, int id) {
    int mid = l + r >> 1;
    nw = ++tot;
    if (l == r) {
        tree[nw].siz = 1;
        tree[nw].id = id;
        return;
    }
    if (pos <= mid) ins(tree[nw].l, l, mid, pos, id);
    else ins(tree[nw].r, mid + 1, r, pos, id);
    push_up(nw);
}

int mer(int l, int r, int x, int y) {// 线段树合并
    if (!x || !y) {
        return (x | y);
    }
    if (l == r) {
        tree[x].siz += tree[y].siz;
        return x;
    }
    int mid = l + r >> 1;
    tree[x].l = mer(l, mid, tree[x].l, tree[y].l);
    tree[x].r = mer(mid + 1, r, tree[x].r, tree[y].r);
    push_up(x);
    return x;
}

int ask(int nw, int l, int r, int k) {
    int mid = l + r >> 1;
    auto &ls = tree[nw].l, &rs = tree[nw].r;
    if (l == r) {
        return (!tree[nw].id ? -1 : tree[nw].id);
    }
    if (tree[ls].siz >= k) {
        return ask(ls, l, mid, k);
    } else {
        return ask(rs, mid + 1, r, k - tree[ls].siz);
    }
}

struct DSU{
    int n, cnt;
    vector<int> fa, siz;
    DSU() {}
    DSU(int n_) : fa(n_ + 1), siz(n_ + 1, 1) {
        n = n_;
        cnt = n;
        iota(fa.begin(), fa.end(), 0);
    }
    
    inline void init() {
		
	}
    
    inline int find(int x) {
        return x == fa[x] ? x : fa[x] = find(fa[x]);
    }
    
    inline bool ral(int x, int y) {
        return find(x) == find(y);
    }
    
    inline bool mergy(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if (fx == fy) return false;
        
        if (siz[fx] > siz[fy]) swap(fx, fy);
        
        cnt--;
        fa[fx] = fy;
        mer(1, n, rt[fy], rt[fx]);
        siz[fy] += siz[fx];
        return true;
    }
};

void solve() {
    int n, m, q;
    cin >> n >> m;
    DSU dsu(n);
    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        ins(rt[i], 1, n, x, i);
    }
    for (int i = 1, u, v; i <= m; i++) {
        cin >> u >> v;
        dsu.mergy(u, v);
    }
    cin >> q;
    for (int i = 1; i <= q; i++) {
        char c;
        cin >> c;
        if (c == 'Q') {
            int x, y;
            cin >> x >> y;
            x = dsu.find(x);
            cout << ask(rt[x], 1, n, y) << '\n';
        } else {
            int x, y;
            cin >> x >> y;
            x = dsu.find(x);
            y = dsu.find(y);
            dsu.mergy(x, y);
        }
    }
}
posted @ 2024-12-26 02:18  grape_king  阅读(19)  评论(0)    收藏  举报