zoukankan      html  css  js  c++  java
  • 可持久化线段树

    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);
        }
    }
    
    
  • 相关阅读:
    uniapp 小程序分享功能
    uniapp 输入有值后按钮变色
    css 跑马灯
    uniapp 复选框问题
    【Python】where cut query melt函数用法
    【Python】Pivot_table透视表用法及CategoricalDtype自定义排序
    【Python】Merge函数的用法
    【Python】extract及contains方法(正则提取筛选数据)
    Promise
    CSS垂直居中的方法
  • 原文地址:https://www.cnblogs.com/EdisonBa/p/14969202.html
Copyright © 2011-2022 走看看