洛谷 [P3224] 永无乡

Posted Mr_Wolfram的高维空间

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 [P3224] 永无乡相关的知识,希望对你有一定的参考价值。

Treap 的合并

首先感谢 @Capella 的DeBug
其次,这是由一个 & 号引发的血案
注意对于所有修改操作都要 &
Treap的合并, 启发式合并,对于每一个节点都 insert ,注意垃圾回收

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int MAXN = 500005;
int init() {
    int rv = 0, fh = 1;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') fh = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        rv = (rv<<1) + (rv<<3) + c - '0';
        c = getchar();
    }
    return fh * rv;
}
int pool[MAXN], top, n, m, id[MAXN], q;
struct UFS {
    int fa[MAXN];
    void unit() {
        for(int i = 1; i <= n; i++) fa[i] = i;
    }
    int find(int x) {
        if(x != fa[x]) return fa[x] = find(fa[x]);
        return fa[x];
    }
}ufs;
struct node{
    int val, dat, num, size, l, r;
}a[MAXN];
struct Treap{
    int New(int x, int num) {
        int ret = pool[++top];
        a[ret].val = x;
        a[ret].num = num;
        a[ret].dat = rand();
        a[ret].size = 1;
        a[ret].l = a[ret].r = 0;
        return ret;
    }
    void del(int &rt) {pool[top--] = rt;rt = 0;}
    void PushUp(int rt) {
        a[rt].size = a[a[rt].l].size + a[a[rt].r].size + 1; 
    }
    void zig(int &rt) {
        int nxt = a[rt].l;
        a[rt].l = a[nxt].r; a[nxt].r = rt; rt = nxt;
        PushUp(a[rt].r);
        PushUp(rt);
    }
    void zag(int &rt) {
        int nxt = a[rt].r;
        a[rt].r = a[nxt].l; a[nxt].l = rt; rt = nxt;
        PushUp(a[rt].l);
        PushUp(rt);
    }
    void Insert(int &rt, int x, int num) {
        if(!rt) {
            rt = New(x, num);
            return;
        }
        if(x < a[rt].val) {
            Insert(a[rt].l, x, num);
            if(a[a[rt].l].dat > a[rt].dat) zig(rt);
        }else {
            Insert(a[rt].r, x, num);
            if(a[a[rt].r].dat > a[rt].dat) zag(rt);
        }
        PushUp(rt);
    }
    int GetNum(int rt, int x) {
        if(!rt) return -1;
        if(a[a[rt].l].size >= x) return GetNum(a[rt].l, x);
        if(a[a[rt].l].size + 1 >=x) return a[rt].num;
        return GetNum(a[rt].r,x - 1 - a[a[rt].l].size);
    }
    void merge(int /*x*/&x, int &y) {
        if(!y) return;
        if(a[y].l) 
        merge(x, a[y].l);
        if(a[y].r) 
        merge(x, a[y].r);
        Insert(x, a[y].val, a[y].num);del(y);
    }
}bst;
void merge(int u, int v) {
    int r1 = ufs.find(u), r2 = ufs.find(v);
    if(r1 != r2) {
        if(a[id[r1]].size < a[id[r2]].size) {
            ufs.fa[r1] = r2;
            bst.merge(id[r2], id[r1]);
        }else {
            ufs.fa[r2] = r1;
            bst.merge(id[r1], id[r2]);
        }
    }
}
int main() {
    n = init(); m = init();
    ufs.unit();
    for(int i = 0; i < MAXN; i++) pool[i] = i;
    for(int i = 1; i <= n; i++) {
        int t = init();
        id[i] = bst.New(t, i);
    }
    for(int i = 1; i <= m; i++) {
        int u = init(), v = init();
        if(!u || !v) continue;
        merge(u, v);
    }
    q = init();
    for(int i = 1; i <= q; i++) {
        char t;
        scanf(" %c ", &t);
        if(t == 'Q') {
            int x = init(), k = init();
            printf("%d\n", bst.GetNum(id[ufs.find(x)], k));
        }else {
            int u = init(), v = init();
            if(!u || !v) continue;
            merge(u, v);
        }
    }
    return 0;
}

以上是关于洛谷 [P3224] 永无乡的主要内容,如果未能解决你的问题,请参考以下文章

P3224 [HNOI2012]永无乡 并查集+线段树合并

[BZOJ2733][P3224][HNOI2012]永无乡[平衡树+启发式合并+并查集]

P3224 [HNOI2012]永无乡 FHQ-Treap 启发式合并

P3224 [HNOI2012]永无乡 FHQ-Treap 启发式合并

P3224 [HNOI2012]永无乡 FHQ-Treap 启发式合并

[HNOI2012] 永无乡