• 可持久化线段树


    P3834 【模板】可持久化线段树 2(主席树)

    这是个非常经典的主席树入门题——静态区间第 (k) 小。

    对于指定的闭区间 ([l, r]) 查询其区间内的第 (k) 小值.

    代码采用指针形式,区间为左闭右闭。

    const ll M = 2e5 + 3;
    int n, N, m, tot, a[M], b[M];
    
    struct node
    {
        int L, R, cnt;
        node *lc, *rc;
    };
    
    struct node by[M * 21], *pool = by, *root[M];
    
    node *New()
    {
        return ++pool;
    }
    
    void update(node *&now)
    {
        now->cnt = now->lc->cnt + now->rc->cnt;
    }
    
    node *build(int l, int r)
    {
        node *now = New();
        now->L = l;
        now->R = r;
        if (l < r)
        {
            int mid = (l + r) >> 1;
            now->lc = build(l, mid);
            now->rc = build(mid + 1, r);
            update(now);
        }
        else
        {
            now->cnt = 0;
            now->lc = now->rc = NULL;
        }
        return now;
    }
    
    inline bool out(node *&now, int l, int r)
    {
        return (now->R < l) || (r < now->L);
    }
    
    void change(node *pre, node *now, int x)
    {
        *now = *pre;
        if (pre->L == x and pre->R == x)
            now->cnt++;
        else
        {
            if (!out(pre->lc, x, x))
            {
                now->lc = New();
                change(pre->lc, now->lc, x);
                update(now);
            }
            else
            {
                now->rc = New();
                change(pre->rc, now->rc, x);
                update(now);
            }
        }
    }
    
    int check(node *&nowl, node *&nowr, int k)
    {
        if (nowl->L == nowl->R)
            return nowl->L;
        int lcnt = nowr->lc->cnt - nowl->lc->cnt;
        if (lcnt >= k)
            return check(nowl->lc, nowr->lc, k);
        else
            return check(nowl->rc, nowr->rc, k - lcnt);
    }
    
    void Main()
    {
        n = read();
        m = read();
        for (int i = 1; i <= n; ++i)
        {
            a[i] = read();
            b[i] = a[i];
        }
        sort(b + 1, b + n + 1);
        N = unique(b + 1, b + n + 1) - b - 1;
        for (int i = 1; i <= n; ++i)
            a[i] = lower_bound(b + 1, b + N + 1, a[i]) - b;
        root[0] = build(1, N);
        for (int i = 1; i <= n; ++i)
        {
            root[++tot] = New();
            change(root[tot - 1], root[tot], a[i]);
        }
        for (int i = 1; i <= m; ++i)
        {
            int l, r, k;
            l = read(), r = read(), k = read();
            int ans = b[check(root[l - 1], root[r], k)];
            printf("%d
    ", ans);
        }
    }
    
    
  • 相关阅读:
    [恢]hdu 2203
    [恢]hdu 2089
    [恢]hdu 1597
    [恢]hdu 1239
    [恢]hdu 2141
    [恢]hdu 2152
    [恢]hdu 2078
    [恢]hdu 2304
    [恢]hdu 1799
    非金钱激励员工的108种手段 ,你一定要懂!
  • 原文地址:https://www.cnblogs.com/EdisonBa/p/14969202.html
Copyright © 2020-2023  润新知