码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷 [P3377] 左偏树(可并堆)

时间:2018-04-27 21:08:14      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:tin   val   str   cpp   clu   void   continue   span   init   

可并堆,就是可以合并的堆

注意并查集不能路径压缩,不然删除根节点时会出错

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAXN = 105005;
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 n, m;
struct LT{
    struct node {
        int l, r, val, dist, fa;
    }a[MAXN];
    int find(int x) {
        if(x != a[x].fa) return find(a[x].fa);
        return a[x].fa;
    }
    int merge(int u, int v) {
        if(!u) return v;
        if(!v) return u;
        if(a[u].val > a[v].val || (a[u].val == a[v].val && u > v)) swap(u, v);
        int &ul = a[u].l, &ur = a[u].r;
        ur = merge(ur, v);
        a[ur].fa = u;
        if(a[ul].dist < a[ur].dist) swap(ur, ul);
        a[u].dist = a[ur].dist + 1;
        return u;
    }
    void input() {
        a[0].dist = -1;
        for(int i = 1; i <= n; i++) a[i].fa = i;
        for(int i = 1; i <= n; i++) a[i].val = init();
    }
    void erase(int u) {
        int ul = a[u].l, ur = a[u].r;
        a[u].val = -1;
        a[ul].fa = ul; a[ur].fa = ur;
        merge(ul, ur);
    }
    void work() {
        input();
        for(int i = 1; i <= m; i++) {
            int opt = init();
            if(opt == 1){
                int x = init(), y = init();
                if(a[x].val == -1 || a[y].val == -1) continue;
                int r1 = find(x), r2 = find(y);
                if(r1 == r2) continue;
                merge(r1, r2);
            }else {
                int x = init();
                if(a[x].val == -1) {
                    printf("-1\n");continue;
                }
                int r1 = find(x);
                printf("%d\n", a[r1].val);
                erase(r1);
            }
        }
    }
}lt;
int main() {
    //freopen("in.txt", "r", stdin);
    n = init(); m = init();
    lt.work();
    //fclose(stdin);
    return 0;
}

洛谷 [P3377] 左偏树(可并堆)

标签:tin   val   str   cpp   clu   void   continue   span   init   

原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8964227.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!