【模板】静态主席树

如题,这是一个模板。。。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cctype>
 6 #include <cmath>
 7
 8 inline void read(int & x)
 9 {
10     x = 0;
11     int k = 1;
12     char c = getchar();
13     while (!isdigit(c))
14         if (c == ‘-‘) c = getchar(), k = -1;
15         else c = getchar();
16     while (isdigit(c))
17         x = (x << 1) + (x << 3) + (c ^ 48),
18         c = getchar();
19     x *= k;
20 }
21
22 const int MAXN = 202020;
23
24 struct sgt
25 {
26     int l, r, w;
27 }t[MAXN << 5];
28
29 int n, m, id = 0, cnt = 0, L, R, K;
30 int root[MAXN], a[MAXN], b[MAXN];
31
32 inline int Lsh(int x) { return std::lower_bound(a + 1, a + cnt + 1, x) - a; }
33
34 void Pushup(int u)
35 {
36     t[u].w = t[t[u].l].w + t[t[u].r].w;
37 }
38
39 void Build(int u, int l, int r)
40 {
41     if (l == r)
42     {
43         t[u].l = -1;
44         t[u].r = -1;
45         t[u].w = 0;
46         return;
47     }
48     t[u].l = ++id;
49     t[u].r = ++id;
50     int mid = (l + r) >> 1;
51     Build(t[u].l, l, mid);
52     Build(t[u].r, mid + 1, r);
53     Pushup(u);
54 }
55
56 int Add(int u, int l, int r, int k)
57 {
58     int cur = ++id;
59     t[cur].l = t[u].l;
60     t[cur].r = t[u].r;
61     t[cur].w = t[u].w + 1;
62     if (l < r)
63     {
64         int mid = (l + r) >> 1;
65         if (k <= mid) t[cur].l = Add(t[u].l, l, mid, k);
66         else t[cur].r = Add(t[u].r, mid + 1, r, k);
67     }
68     return cur;
69 }
70
71 int Query(int u, int v, int l, int r, int k)
72 {
73     if (l == r) return l;
74     int df = t[t[v].l].w - t[t[u].l].w;
75     int mid = (l + r) >> 1;
76     if (df < k) return Query(t[u].r, t[v].r, mid + 1, r, k - df);
77     else return Query(t[u].l, t[v].l, l, mid, k);
78 }
79
80 signed main()
81 {
82     read(n), read(m);
83     for (int i = 1; i <= n; ++i) read(a[i]), b[i] = a[i];
84     std::sort(a + 1, a + n + 1);
85     cnt = std::unique(a + 1, a + n + 1) - a - 1;
86     Build(root[0] = ++id, 1, cnt);
87     for (int i = 1; i <= n; ++i)
88         root[i] = Add(root[i - 1], 1, cnt, Lsh(b[i]));
89     for (int i = 1; i <= m; ++i)
90     {
91         read(L), read(R), read(K);
92         int p = Query(root[L - 1], root[R], 1, cnt, K);
93         printf("%d\n", a[p]);
94     }
95     return 0;
96 }

原文地址:https://www.cnblogs.com/yanyiming10243247/p/10057781.html

时间: 2024-11-05 13:45:50

【模板】静态主席树的相关文章

ZOJ 2112 Dynamic Rankings(主席树套树状数组+静态主席树)

题意:给定一个区间,求这个区间第k大的数,支持单点修改. 思路:主席树真是个神奇的东西.........速度很快但是也有一个问题就是占用内存的很大,一般来说支持单点修改的主席树套树状数组空间复杂度为O(n*logn*logn), 如果查询较少的话,可以初始的时候用一颗静态主席树,这样空间复杂度可以降为O(n*logn+q*logn*logn),勉强可以过zoj这道题. 这道题看了好久好久才懂...网上题解一般就几句话.......下面是自己的一些理解. 首先静态主席树这个东西其实比较好懂,就是对

静态主席树总结(静态区间的k大)

静态主席树总结(静态区间的k大) 首先我们先来看一道题 给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入格式: 第一行包含两个正整数N.M,分别表示序列的长度和查询的个数. 第二行包含N个正整数,表示这个序列各项的数字. 接下来M行每行包含三个整数 l, r, kl,r,k , 表示查询区间[l, r][l,r] 内的第k小值. 输出格式: 输出包含k行,每行1个正整数,依次表示每一次查询的结果 对于100%的数据满足:\(1 \leq N, M \leq 2\cdot

[Luogu 3701] 「伪模板」主席树

[Luogu 3701] 「伪模板」主席树 <题目链接> 这是一道网络流,不是主席树,不是什么数据结构,而是网络流. 题目背景及描述都非常的暴力,以至于 Capella 在做此题的过程中不禁感到生命流逝. S 向 byx 的树中的每一个人连有向边,手气君的树中的每一个人向 T 连有向边,边权为这个人的寿命.统计同一棵树中的膜法师数量 x.如果一个人是主席,那么边权要加上 x.(续得好啊) 然后,如果 byx 树中的一个点 i 能赢手气君树中的点 j,那么连 i->j,边权为 1. 跑最大

P3701 「伪模板」主席树

P3701 「伪模板」主席树 题目背景 byx和手气君都非常都非常喜欢种树.有一天,他们得到了两颗奇怪的树种,于是各自取了一颗回家种树,并约定几年后比一比谁种出来的树更加牛x. 题目描述 很快,这棵树就开花结果了.byx和手气君惊讶的发现,这是一棵主席树,树上长满了主席和主席的朋友们.这棵树上一共有五种人,主席(J),记者(HK),高人(W),女王(E)和膜法师(YYY).他们发现,他们的主席树上的人数相同,都为N. 研究发现,这五种人的输赢如上图所示(一样的人不能PK),箭头指向输的人.至于为

poj2104求区间第k小,静态主席树入门模板

看了很久的主席树,最后看https://blog.csdn.net/williamsun0122/article/details/77871278这篇终于看懂了 #include <stdio.h> #include<algorithm> using namespace std; typedef long long ll; const int maxn = 1e5+5; int T[maxn],L[maxn*20],R[maxn*20],sum[maxn*20]; //sz[]为原

poj 2104 静态主席树

我的第一道主席树(静态). 先记下自己对主席树的理解: 主席树的作用是用于查询区间第k大的元素(初始化nlog(n),查询log(n)) 主席树=可持续线段树+前缀和思想 主席树实际上是n棵线段树(由于是可持续化线段树,所以实际上是n个长度为log(n)的链),第i棵线段树保存的是a[1]~a[i]这i个数的值域线段树,每个节点维护的是该值域中元素个数,这个是可以相减的,所以建完树后,查询[lf,rg]的第k大时,保存当前查询的值域区间在lf-1和rg这两棵线段树中的节点u,v(不理解看代码),

【Luogu】P3384主席树模板(主席树查询K小数)

YEAH!我也是一个AC主席树模板的人了! 其实是个半吊子 我将尽量详细的讲出我的想法. 主席树太难,我们先搞普通线段树好了 普通线段树怎么做?我的想法是查询K次最小值,每次查完把查的数改成INF,查完再改回来... MDZZ 于是就有了主席树. 先不考虑主席树,我们来考虑一个奇特的线段树. 一般的线段树,数列位置是下标,而把数列维护值作为线段树中存的元素. 那我们如果反过来,把数列元素当做线段树的下标...??? 比如说数列[4 2 3 1] 如果线段树的下标是1.2.3.4......? 那

静态主席树

[转]主席树:对于序列的每一个前缀建一棵以序列里的值为下标的线段树(所以要先离散化),记录该前缀序列里出现的值的次数:记离散后的标记为1~n; (下面值直接用1~n代替;) 对于区间[x,y]的第k大的值,那么从root[x-1],root[y]开始,t=root[y].[1,mid]-root[x-1].[1,mid] ,t表示区间[x,y]内值在[1,mid]的个数 先判断t是否大于K. 如果t大于k,那么说明在区间[x,y]内存在[1,mid]的数的个数大于k,也就是第k大的值在[1,mi

【模板】主席树

主席树..高大上的名字..原名叫可持久化线段树..也有人叫函数式线段树(其实叫什么都不重要). 本来的作用就是字面意思..持久化的线段树,支持修改之后查找某次修改之前的版本.(在NOIP之前在算法导论上看到过,当时觉得没什么,现在才知道好厉害的数据结构) 具体来怎么实现呢..其实就是每次修改的时候都新开一个根节点然后把和修改有关的区间一路新建下去,与修改无关的区间就继承上次修改版本的节点,这样会节省空间. 来应用一下,一个基础的应用就是区间K小值查询(poj2104).即给定一个序列,给出L,R

洛谷 3701「伪模板」主席树(最大流)

题目背景 byx和手气君都非常都非常喜欢种树.有一天,他们得到了两颗奇怪的树种,于是各自取了一颗回家种树,并约定几年后比一比谁种出来的树更加牛x. 题目描述 很快,这棵树就开花结果了.byx和手气君惊讶的发现,这是一棵主席树,树上长满了主席和主席的朋友们.这棵树上一共有五种人,主席(J),记者(HK),高人(W),女王(E)和膜法师(YYY).他们发现,他们的主席树上的人数相同,都为N.   研究发现,这五种人的输赢如上图所示(一样的人不能PK),箭头指向输的人.至于为什么,留给同学们自己思考.