zoukankan      html  css  js  c++  java
  • [HNOI2012]永无乡 线段树合并

    [HNOI2012]永无乡

    LG传送门

    线段树合并练手题,写这篇博客只是为了给我的这篇文章找个板子题。

    并查集维护连通性,对于不在同一个连通块内的合并操作每次直接合并两颗线段树,复杂度(O(n log n))

    //written by newbiechd
    #include <cstdio>
    #define R register
    #define I inline
    using namespace std;
    const int N = 100003;
    int f[N], id[N], rt[N], T;
    struct segtree {
        int p, q, s;
    }e[N << 5];
    I int find(int x) {
        R int r = x, y;
        while (f[r] ^ r)
            r = f[r];
        while (x ^ r)
            y = f[x], f[x] = r, x = y;
        return r;
    }
    void insert(int &k, int l, int r, int x) {
        k = ++T, ++e[k].s;
        if (l == r)
            return ;
        R int m = (l + r) >> 1;
        if (x <= m)
            insert(e[k].p, l, m, x);
        else
            insert(e[k].q, m + 1, r, x);
    }
    int merge(int k, int t, int l, int r) {
        if (!k)
            return t;
        if (!t)
            return k;
        e[k].s += e[t].s;
        if (l == r)
            return k;
        R int m = (l + r) >> 1;
        e[k].p = merge(e[k].p, e[t].p, l, m),
            e[k].q = merge(e[k].q, e[t].q, m + 1, r);
        return k;
    }
    int query(int k, int l, int r, int x) {
        if (l == r)
            return l;
        R int m = (l + r) >> 1, t = e[e[k].p].s;
        if (x <= t)
            return query(e[k].p, l, m, x);
        else
            return query(e[k].q, m + 1, r, x - t);
    }
    int main() {
        R int n, m, Q, i, x, y, z;
        R char opt[2];
        scanf("%d%d", &n, &m);
        for (i = 1; i <= n; ++i)
            f[i] = i, scanf("%d", &z), id[z] = i, insert(rt[i], 1, n, z);
        for (i = 1; i <= m; ++i)
            scanf("%d%d", &x, &y), x = find(x), y = find(y), f[y] = x,
                rt[x] = merge(rt[x], rt[y], 1, n);
        scanf("%d", &Q);
        for (i = 1; i <= Q; ++i) {
            scanf("%s%d%d", opt, &x, &y), x = find(x);
            if (opt[0] == 'B') {
                y = find(y);
                if (y ^ x)
                    f[y] = x, merge(rt[x], rt[y], 1, n);
            }
            else
                if (y > e[rt[x]].s)
                    printf("-1
    ");
                else
                    printf("%d
    ", id[query(rt[x], 1, n, y)]);
        }
        return 0;
    }
    
    
  • 相关阅读:
    C# 中文件路径的操作
    字符串模式匹配KMP算法
    SLG游戏关卡设计
    android 源码包结构分析
    NIO的理解
    显示单位
    多线程时控制并发数据库操作的思路
    使用异常机制的建议
    合理的使用索引。《Map的使用》
    android源码的下载方法Windows
  • 原文地址:https://www.cnblogs.com/cj-chd/p/10433154.html
Copyright © 2011-2022 走看看