【模板】 主席树

 1 // poj2104
 2 // p3834
 3 #include<iostream>
 4 #include<cstdio>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=1e5+7;
 8 int a[N],b[N],rt[N];
 9 int cnt=0;
10 struct node{
11     int l,r,sum;
12 }tr[N*20];
13 void build(int& o,int l,int r){
14     o=++cnt;
15     if(l==r) return;
16     int m=(l+r)>>1;
17     build(tr[o].l,l,m);
18     build(tr[o].r,m+1,r);
19 }
20 void change(int& neo,int pro,int l,int r,int p){
21     neo=++cnt;tr[neo]=tr[pro];++tr[neo].sum;
22     if(l==r) return;
23     int m=(l+r)>>1;
24     if(p<=m) change(tr[neo].l,tr[pro].l,l,m,p);
25     else change(tr[neo].r,tr[pro].r,m+1,r,p);
26 }
27 int query(int rtl,int rtr,int l,int r,int k){
28     if(l==r) return b[l];
29     int x=tr[tr[rtr].l].sum-tr[tr[rtl].l].sum;
30     int m=(l+r)>>1;
31     if(x>=k) return query(tr[rtl].l,tr[rtr].l,l,m,k);
32     else return query(tr[rtl].r,tr[rtr].r,m+1,r,k-x);
33 }
34 int main(){
35     int n,m;scanf("%d%d",&n,&m);
36     for(int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i];
37     sort(b+1,b+1+n);
38     int num=unique(b+1,b+1+n)-b-1;
39     build(rt[0],1,num);
40     for(int i=1;i<=n;++i){
41         int p=lower_bound(b+1,b+1+num,a[i])-b;
42         change(rt[i],rt[i-1],1,num,p);
43     }
44     for(int i=1;i<=m;++i){
45         int l,r,k;scanf("%d%d%d",&l,&r,&k);
46         printf("%d\n",query(rt[l-1],rt[r],1,num,k));
47     }
48     return 0;
49 }

原文地址:https://www.cnblogs.com/xiaobuxie/p/11391857.html

时间: 2024-10-08 09:54:25

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

【POJ 2104】 K-th Number 主席树模板题

达神主席树讲解传送门:http://blog.csdn.net/dad3zz/article/details/50638026 2016-02-23:真的是模板题诶,主席树模板水过.今天新校网不好,没有评测,但我立下flag这个代码一定能A.我的同学在自习课上考语文,然而机房党都跑到机房来避难了\(^o^)/~ #include<cstdio> #include<cstring> #include<algorithm> #define for1(i,a,n) for(i

【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题

达神题解传送门:http://blog.csdn.net/dad3zz/article/details/50638360 说一下我对这个模板的理解: 看到这个方法很容易不知所措,因为动态K值需要套树状数组,而我一开始根本不知道该怎么套,, 学习吧,,, 然后我自己脑补如果不套会如何?后来想到是查询O(logn),修改是O(nlogn),很明显修改的复杂度太大了,为了降低修改的复杂度,我们只得套上树状数组来维护前缀和使它的n的复杂度降低为logn,从而修改的复杂度变为O(log2n).但因为我们套

bzoj2223 [Coci 2009]PATULJCI (模板)(主席树)

2223: [Coci 2009]PATULJCI Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1245  Solved: 530[Submit][Status][Discuss] Description HINT 输入第二个整数是序列中权值的范围Lim,即1<=ai(1<=i<=n)<=Lim,1<=Lim<=10000. 主席树模板dearu: 蒟蒻只能码板子了啊(摊): ↓代码 1 #include<ios

主席树模板

#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int M = 50006; int w[M], a[M], root[M]; struct Tree{ int ls, rs, w; } tr[M << 4] ; int tot ; void insert(int &x, int l, int r, int d){ tr[++tot]

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

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

【刷题】洛谷 P3834 【模板】可持久化线段树 1(主席树)

题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示序列的长度和查询的个数. 第二行包含N个正整数,表示这个序列各项的数字. 接下来M行每行包含三个整数l, r, kl,r,k , 表示查询区间[l, r][l,r] 内的第k小值. 输出格式: 输出包含k行,每行1个正整数,依次表示每一次查询的

[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),箭头指向输的人.至于为

主席树的各类模板(区间第k大数【动,静】,区间不同数的个数,区间&lt;=k的个数)

取板粗 1.(HDOJ2665)http://acm.hdu.edu.cn/showproblem.php?pid=2665 (POJ2104)http://poj.org/problem?id=2104 (POJ2761)http://poj.org/problem?id=2761 题意:求区间第K大,主席树模板题 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; t

【模板】【数据结构】【树】主席树

技巧一:离散去重 for(int i=1;i<=n;i++) scanf("%d",&a[i] ),b[i]=a[i]; sort(b+1,b+n+1); int nn=unique(b+1,b+n+1)-b-1;//假设有x个数,那么nn指针会停在第x+1个数的位置 ,nn及以后的都是重复的元素for(int i=1;i<=n;i++) id[i]=lower_bound(b+1,b+nn+1,a[i])-b;//离散过后的新value 技巧二:可持久化数据结构