zoukankan      html  css  js  c++  java
  • 主席树

    一种可持续化的数据结构

    可用于计算区间第(k)

    主席树详解

    [模板]可持久化线段树1(主席树)

    题目链接

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define maxn 200100
    int n, q;
    int a[maxn], b[maxn], root[maxn];
    int cnt = 0;
    int lz[maxn << 5], rz[maxn << 5], sum[maxn << 5];
    int build(int l, int r)
    {
        int rt = ++cnt;
        sum[rt] = 0;
        int mid = (l + r) >> 1;
        if(l == r) return rt;
        lz[rt] = build(l, mid);
        rz[rt] = build(mid + 1, r);
        return rt;
    }
    int update(int pre, int l, int r, int x)
    {
        int rt = ++cnt;
        lz[rt] = lz[pre]; rz[rt] = rz[pre]; sum[rt] = sum[pre] + 1;
        if(l == r) return rt;
        int mid = (l + r) >> 1;
        if(mid >= x) lz[rt] = update(lz[pre], l, mid, x);
        if(mid < x) rz[rt] = update(rz[pre], mid + 1, r, x);
        return rt;
    }
    int query(int u, int v, int l, int r, int k)
    {
        int x = sum[lz[v]] - sum[lz[u]];
        int mid = (l + r) >> 1;
        if(l == r) return l;
        if(k <= x) return query(lz[u], lz[v], l, mid, k);
        else return query(rz[u], rz[v], mid + 1, r, k - x);
    }
    int main()
    {
        scanf("%d%d", &n, &q);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
        sort(b + 1, b + n + 1);
        int m = unique(b + 1, b + n + 1) - (b + 1);
        root[0] = build(1, m);
        for(int i = 1; i <= n; i++)
        {
            int x = lower_bound(b + 1, b + m + 1, a[i]) - b;
            root[i] = update(root[i - 1], 1, m, x);
        }
        for(int i = 1; i <= q; i++)
        {
            int l, r, k;
            scanf("%d%d%d", &l, &r, &k);
            int t = query(root[l - 1], root[r], 1, m, k);
            printf("%d
    ", b[t]);
        }
        return 0;
    }
    

    [模板]可持久化数组

    题目链接

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define maxn 1000100
    int n, q;
    int cnt = 0;
    int a[maxn], b[maxn];
    int sum[maxn << 5], root[maxn << 5];
    int lz[maxn << 5], rz[maxn << 5];
    int build(int l, int r)
    {
        int rt = ++cnt;
        if(l == r)
        {
            sum[rt] = a[l];
            return rt;
        }
        int mid = (l + r) >> 1;
        lz[rt] = build(l, mid);
        rz[rt] = build(mid + 1, r);
        return rt;
    }
    int update(int pre, int l, int r, int x, int v)
    {
        int rt = ++cnt;
        lz[rt] = lz[pre]; rz[rt] = rz[pre];
        if(l == r)
        {
            sum[rt] = v; return rt;
        }
        int mid = (l + r) >> 1;
        if(mid >= x) lz[rt] = update(lz[pre], l, mid, x, v);
        if(mid < x) rz[rt] = update(rz[pre], mid + 1, r, x, v);
        return rt;
    }
    int ans = 0;
    int query(int k, int l, int r, int x)
    {
        if(l == r)
        {
            return sum[k];
        }
        int mid = (l + r) >> 1;
        if(mid >= x) return query(lz[k], l, mid, x);
        if(mid < x) return query(rz[k], mid + 1, r, x);
    }
    int main()
    {
        scanf("%d%d", &n, &q);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        root[0] = build(1, n);
        for(int i = 1; i <= q; i++)
        {
            int pre; scanf("%d", &pre);
            int op; scanf("%d", &op);
            if(op == 1)
            {
                int x, v; scanf("%d%d", &x, &v);
                root[i] = update(root[pre], 1, n, x, v);
            }
            if(op == 2)
            {
                int x; scanf("%d", &x);
                root[i] = root[pre];
                printf("%d
    ", query(root[pre], 1, n, x));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    刚刚开通
    腾讯面试经历2015
    排序之归并排序
    AC自动机
    后缀数组初步
    概率dp初探
    【NOIP2015】反思+题解
    Built-in functions
    poj2528 Mayor's posters(线段树区间覆盖)
    Codeforces #317 C.Lengthening Sticks(数学)
  • 原文地址:https://www.cnblogs.com/Akaina/p/11839508.html
Copyright © 2011-2022 走看看