首页 > 其他分享 >P3834 【模板】可持久化线段树 2

P3834 【模板】可持久化线段树 2

时间:2024-08-07 19:38:31浏览次数:8  
标签:lc int 线段 tr P3834 build sum 模板 PersidentSegmentTree

P3834 【模板】可持久化线段树 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

template<class Node>
struct PersidentSegmentTree {
#define lc(u) tr[u].l
#define rc(u) tr[u].r
#define sum(u) tr[u].s
    const int n;
    int tot = 0;
    vector<Node> tr;
    vector<int> root;

    PersidentSegmentTree(): n(0) {}

    PersidentSegmentTree(int n_): n(n_) {
        int N = (n << 7) + 10;
        tr.reserve(N); root.reserve(N);
        tr.resize(N); root.resize(N);

        function<void(int&, int, int)> build = [&](int& u, int l, int r) {
            u = ++ tot;
            sum(u) = 0;
            if (l == r) {javascript:void(0);
                return ;
            }
            int m = (l + r) >> 1;
            build(lc(u), l, m);
            build(rc(u), m + 1, r);
        };
        build(root[0], 1, n);
    }

    void insert(int u, int& v, int l, int r, int pos) {
        v = ++ tot;
        tr[v] = tr[u], sum(v) = sum(u) + 1;
        if (l == r)
            return;
        int m = l + r >> 1;
        if (pos <= m)
            insert(lc(u), lc(v), l, m, pos);
        else
            insert(rc(u), rc(v), m + 1, r, pos);
    }

    int query(int u, int v, int l, int r, int k) {
        if (l == r)
            return l;

        int m = l + r >> 1, s = sum(lc(v)) - sum(lc(u));
        if (k <= s)
            return query(lc(u), lc(v), l, m, k);
        else
            return query(rc(u), rc(v), m + 1, r, k - s);
    }
};

struct Node {
    int l, r, s;
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, q;
    cin >> n >> q;

    vector<int> b(n + 1);
    for (int i = 1; i <= n; i ++)
        cin >> b[i];

    auto a = b;
    sort(a.begin() + 1, a.end());
    int m = unique(a.begin() + 1, a.end()) - a.begin() - 1;

    PersidentSegmentTree<Node> PST(m);

    for (int i = 1; i <= n; i ++) {
        int idx = lower_bound(a.begin() + 1, a.begin() + m + 1, b[i]) - a.begin();
        PST.insert(PST.root[i - 1], PST.root[i], 1, m, idx);
    }

    while (q--) {
        int l, r, k;
        cin >> l >> r >> k;
        int idx = PST.query(PST.root[l - 1], PST.root[r], 1, m, k);
        cout << a[idx] << '\n';
    }

    return 0;
}

标签:lc,int,线段,tr,P3834,build,sum,模板,PersidentSegmentTree
From: https://www.cnblogs.com/Kescholar/p/18347765

相关文章

  • 主席树模板
    template<classNode>structPersidentSegmentTree{#definelc(u)tr[u].l#definerc(u)tr[u].r#definesum(u)tr[u].sconstintn;inttot=0;vector<Node>tr;vector<int>root;PersidentSegmentTree():n(0){}......
  • 洛谷P3842 线段——题解
    洛谷P3842题解传送锚点摸鱼环节[TJOI2007]线段题目描述在一个\(n\timesn\)的平面上,在每一行中有一条线段,第\(i\)行的线段的左端点是\((i,L_{i})\),右端点是\((i,R_{i})\)。你从\((1,1)\)点出发,要求沿途走过所有的线段,最终到达\((n,n)\)点,且所走的路程长度要尽......
  • P10814 【模板】离线二维数点
    原题链接题解对于一段区间\([l,r]\)我们可以在\(r\)的位置查询一次,然后利用差分的思想跑到l-1再查一次虽然这样不行,但是可以先在\(l-1\)的位置查询一次,然后再在\(r\)的位置查询一次,然后顺序遍历,每次遍历就把对应位置上的数激活,可以用树状数组code#include<bits/stdc+......
  • 数据结构——线段树优化 学习笔记
    数据结构——线段树优化学习笔记比较基础,因此讲的很快。我们主要关注单点修改、区间查询的线段树,这是应用最广泛的。线段树问题我们以LOJ的这道题为例,例题:LOJ#130.树状数组1:单点修改,区间查询。洛谷上面也有类似的题:P3374【模板】树状数组1。因为洛谷的题的数据范......
  • 数据结构——线段树提高 学习笔记
    数据结构——线段树提高学习笔记一些比较系统的东西,会单独放文章,这里只写一些理论的。线段树维护矩阵例题:P7453[THUSCH2017]大魔法师。当区间信息比较复杂,但是满足结合律的时候,可以使用矩阵维护。线段树每个节点维护一个矩阵,合并区间时使用矩阵乘法转移。但是,矩阵乘法的......
  • 模板
    [置顶]缺省源#include<bits/stdc++.h>#defineDebugputs("Oops!")//#defineintlonglongusingnamespacestd;constintN=1e5+5,M=5e5+5;inlineintread(){ intx=0,f=1;charc=getchar(); while(!isdigit(c)){if(c=='-......
  • kmp算法模板
    模板//pi代表前缀函数 //pi[i]:s[0~i]的最长匹配真前后缀长度 vecotr<int>pi(str.size()); //求前缀函数 for(inti=1;i<str.size();i++){ intlen=pi[i-1];//前一个值的pilen是我们想要找到的一个长度值 while(len!=0&&str[i]!=str[len]){//不匹配时,......
  • 织梦DEDECMS列表页首页怎么跟其它页使用不同模板
    有些时候我们需要使列表页的首页跟第二页以及后面的页面的样式不同,修改dede:list标签又很难达到理想的效果,那么织梦猫就为大家介绍一个最简单的办法,就是为首页单独指定一个模板页,其余页面则调用另一个模板页。修改的办法如下:打开include目录下的arc.listview.class.php文件,找到D......
  • 洛谷P1226 【模板】快速幂
    1.快速幂模板前置知识一个数字n,它的二进制位数一定是log2n向下取整+1;快速幂模板代码这段代码实现了快速幂算法(Exponentiationbysquaring),用来计算(an)的值,其中(a)和(n)都是整数。intquickpow(inta,intn){intres=1;//初始化结果为1,因为任何数的......
  • 【CDQ分治】【模板】三维偏序(陌上花开)
    P3810【模板】三维偏序(陌上花开)-洛谷|计算机科学教育新生态(luogu.com.cn)#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;template<typenameT>structBIT{#ifndeflowbit#definelowbit(x)(x&(-x));#endifintn;vector<T&......