【刷题】洛谷 P3834 【模板】可持久化线段树 1(主席树)
题目背景
这是个非常经典的主席树入门题——静态区间第K小
数据已经过加强,请使用主席树。同时请注意常数优化
题目描述
如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值。
输入输出格式
输入格式:
第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。
第二行包含N个正整数,表示这个序列各项的数字。
接下来M行每行包含三个整数l, r, kl,r,k , 表示查询区间[l, r][l,r] 内的第k小值。
输出格式:
输出包含k行,每行1个正整数,依次表示每一次查询的结果
输入输出样例
输入样例#1:
5 5
25957 6405 15770 26287 26465
2 2 1
3 4 1
4 5 1
1 2 2
4 4 1
输出样例#1:
6405
15770
26287
25957
26287
说明
数据范围:
对于20%的数据满足:\(1 \leq N, M \leq 10\)
对于50%的数据满足:\(1 \leq N, M \leq 10^3\)
对于80%的数据满足:\(1 \leq N, M \leq 10^5\)
对于100%的数据满足:\(1 \leq N, M \leq 2\cdot 10^5\)
对于数列中的所有数\(a_i\) ,均满足\(-{10}^9 \leq a_i \leq {10}^9\)
样例数据说明:
N=5,数列长度为5,数列从第一项开始依次为\([25957, 6405, 15770, 26287, 26465 ]\)
第一次查询为\([2, 2]\) 区间内的第一小值,即为6405
第二次查询为\([3, 4]\) 区间内的第一小值,即为15770
第三次查询为\([4, 5]\) 区间内的第一小值,即为26287
第四次查询为\([1, 2]\) 区间内的第二小值,即为25957
第五次查询为\([4, 4]\) 区间内的第一小值,即为26287
题解
主席树
这道题当作是我学习主席树的开端吧,模板题
主席树维护的是区间,但这个区间不是下标(即位置)的区间,而是权值的区间
在一个版本中
- 区间\([l,l]\)上记录的是\(l\)这个数出现了多少次
- 区间\([l,r]\)上记录的就是\(l,l+1,...,r-1,r\)每个数出现次数之和了
所以要先离散化
主席树说白了就是给一个长度为\(n\)的序列建\(n\)棵权值线段树,第\(i\)棵线段树只存了\(a_1,a_2,a_3,...a_{i-1},a_i\)
这样我们对于本题这样的静态查询第\(k\)小,就可以差分了(想一想原理)
然后发现相邻两棵线段树改变的只有一条路径上的值,其它的值都是一样的,那么为了节省空间,我们把那些值一样的存在同一个节点(即共用节点),就不用再开节点了
同时,我们称第\(i\)棵线段树为第\(i\)个版本
差分的话,就是
如果要查询\([l,r]\)中的信息,那么我们看
第\(r\)棵线段树记录的是\(a_1,a_2,...,a_r\)中的信息
第\(l-1\)棵线段树记录的是\(a_1,a_2,...a_{l-1}\)中的信息
它们相减后,就变成\(a_l,a_{l+1},...,a_r\)中的信息了
而它们能够相减的依据是:每一棵线段树每一个节点维护的内容是一样的(只是其中的值不一样而已)
#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
#define Mid ((l+r)>>1)
#define lson l,Mid
#define rson Mid+1,r
const int MAXN=200000+10;
int n,m,A[MAXN];
struct ChairMan_Tree{
int sum[MAXN<<5],lc[MAXN<<5],rc[MAXN<<5],cnt,root[MAXN];
inline void init()
{
memset(sum,0,sizeof(sum));
memset(lc,0,sizeof(lc));
memset(rc,0,sizeof(rc));
cnt=0;
}
inline void Build(int &rt,int l,int r)
{
rt=++cnt;
sum[rt]=0;
if(l==r)return ;
Build(lc[rt],lson);
Build(rc[rt],rson);
}
inline void Insert(int &rt,int l,int r,int last,int pos)
{
rt=++cnt;
lc[rt]=lc[last];
rc[rt]=rc[last];
sum[rt]=sum[last]+1;
if(l==r)return ;
else
{
if(pos<=Mid)Insert(lc[rt],lson,lc[last],pos);
else Insert(rc[rt],rson,rc[last],pos);
}
};
inline int Query(int now,int last,int l,int r,int k)
{
if(l==r)return l;
else
{
int t=sum[lc[now]]-sum[lc[last]];
if(k<=t)return Query(lc[now],lc[last],lson,k);
else return Query(rc[now],rc[last],rson,k-t);
}
};
};
ChairMan_Tree T;
std::vector<int> V;
std::map<int,int> M;
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void discre()
{
sort(V.begin(),V.end());
V.erase(unique(V.begin(),V.end()),V.end());
for(register int i=1;i<=n;++i)
{
int pre=A[i];
A[i]=lower_bound(V.begin(),V.end(),A[i])-V.begin()+1;
M[A[i]]=pre;
}
}
int main()
{
read(n);read(m);
T.init();
T.Build(T.root[0],1,n);
for(register int i=1;i<=n;++i)
{
read(A[i]);
V.push_back(A[i]);
}
discre();
for(register int i=1;i<=n;++i)T.Insert(T.root[i],1,n,T.root[i-1],A[i]);
while(m--)
{
int l,r,k;
read(l);read(r);read(k);
write(M[T.Query(T.root[r],T.root[l-1],1,n,k)],'\n');
}
return 0;
}
【刷题】洛谷 P3834 【模板】可持久化线段树 1(主席树)的更多相关文章
- 洛谷P3834 [模板]可持久化线段树1(主席树) [主席树]
题目传送门 可持久化线段树1(主席树) 题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定 ...
- 【洛谷 P3834】 可持久化线段树1(主席树)
题目链接 主席树=可持久化权值线段树. 如果你不会可持久化线段树,请右转 如果你不会权值线段树,请自行脑补,就是线段树维护值域里有多少个数出现. 可持久化线段树是支持查询历史版本的. 我们对每个数都进 ...
- 洛谷.3834.[模板]可持久化线段树(主席树 静态区间第k小)
题目链接 //离散化后范围1~cnt不要错 #include<cstdio> #include<cctype> #include<algorithm> //#def ...
- 洛谷P4559 [JSOI2018]列队 【70分二分 + 主席树】
题目链接 洛谷P4559 题解 只会做\(70\)分的\(O(nlog^2n)\) 如果本来就在区间内的人是不用动的,区间右边的人往区间最右的那些空位跑,区间左边的人往区间最左的那些空位跑 找到这些空 ...
- 洛谷$P$2468 粟粟的书架 $[SDOI2010]$ 主席树
正解:主席树 解题报告: 传送门! 题目大意是说,给定一个矩形,然后每次会给一个,这个大矩形中的一个小矩形,询问从小矩形中最少选多少个数字能满足它们之和大于等于给定数字$x$ 看起来很神的样子,完全不 ...
- 洛谷.3835.[模板]可持久化平衡树(fhq treap)
题目链接 对每次Merge(),Split()时产生的节点都复制一份(其实和主席树一样).时间空间复杂度都为O(qlogq).(应该更大些 因为rand()?内存真的爆炸..) 对于无修改的操作实际上 ...
- ☆ [洛谷P2633] Count on a tree 「树上主席树」
题目类型:主席树+\(LCA\) 传送门:>Here< 题意:给出一棵树.每个节点有点权.问某一条路径上排名第\(K\)小的点权是多少 解题思路 类似区间第\(K\)小,但放在了树上. 考 ...
- 【洛谷 P2633】 Count on a tree(主席树,树上差分)
题目链接 思维难度0 实现难度7 建出主席树后用两点的状态减去lca和lca父亲的状态,然后在新树上跑第\(k\)小 #include <cstdio> #include <cstr ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665
如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...
随机推荐
- 模拟websocket推送消息服务mock工具二
模拟websocket推送消息服务mock工具二 在上一篇博文中有提到<使用electron开发一个h5的客户端应用创建http服务模拟后端接口mock>使用electron创建一个模拟后 ...
- react-native初体验(1) — hello world
没有简介,直接开始干活吧. 默认阅读本文的你已经安装好 nodejs, windows用户需要升级yarn到最新版本. 并且设置安装源为国内的淘宝源: npm config set registry ...
- MergeSort 归并排序(java)
MergeSort 归并排序 排序思想:1,分解待排序的n个元素为两个子列,各为n/2个元素 2,若子列没有排好序,重复1步骤,每个子列继续分解为两个子列,直至被分解的子列个数为1 3,子列元素个数为 ...
- 如何判断Map中的key或value类型
在上班写工具类时,遇到了一个问题,将xml文件的节点都放入map容器中时,map的value也是一个map,导致取map的value时,需要判断这个value的数据类型,用到了一下说的这些知识: 对于 ...
- docker usage
docker ps -a 查看物理机上面所有容器信息列表 docker exec -it $docker_id /bin/bash 进入容器以默认帐号 docker exec -it -u root ...
- netcore如何引用package?
netcore项目引用dll包,分如下三种: 1.引用网络包 从nuget获取,然后引入,使用命令:dotnet add package 包名 然后:dotnet restore 2.引用同解决方案的 ...
- kafka handler
1.配置kafka 参数文件 在ogg主目录下有示例文件: [root@WH0PRDBRP00AP0013 ogg]# cd AdapterExamples/big-data/kafka/ [root ...
- 【转】Java生成plist下载ipa文件
我们在上传ipa想要安装的时候必须要通过plist文件去下载,并且还要遵循 itms-services协议. 意思就是,第一步我们要生成一个plist文件, 第二步生成一个html文件,用来指向pli ...
- comet4j推送 405/500 JSON转换异常
因为Comet4J工作在NIO方式下,所以我们需要调整服务器连接器配置,更换为NOI连接器. 打开server.xml文件将找到原先的连接器配置: <Connector executor=&qu ...
- 作业MathExam
MathExam233 一.预估与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 600 650 • ...