POJ 2104 K-th Number && 洛谷 P3834 【模板】可持久化线段树 1(主席树)
我惊奇的发现这两道题一模一样
题目背景
这是个非常经典的主席树入门题——静态区间第K小
数据已经过加强,请使用主席树。同时请注意常数优化
题目描述
如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值。
输入输出格式
输入格式:
第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。
第二行包含N个整数,表示这个序列各项的数字。
接下来M行每行包含三个整数l, r, kl,r,k , 表示查询区间[l, r][l,r]内的第k小值。
输出格式:
输出包含k行,每行1个整数,依次表示每一次查询的结果
输入输出样例
5 5
25957 6405 15770 26287 26465
2 2 1
3 4 1
4 5 1
1 2 2
4 4 1
6405
15770
26287
25957
26287
说明
数据范围:
对于20%的数据满足:1 \leq N, M \leq 101≤N,M≤10
对于50%的数据满足:1 \leq N, M \leq 10^31≤N,M≤103
对于80%的数据满足:1 \leq N, M \leq 10^51≤N,M≤105
对于100%的数据满足:1 \leq N, M \leq 2\cdot 10^51≤N,M≤2⋅105
对于数列中的所有数a_iai,均满足-{10}^9 \leq a_i \leq {10}^9−109≤ai≤109
样例数据说明:
N=5,数列长度为5,数列从第一项开始依次为[25957, 6405, 15770, 26287, 26465 ][25957,6405,15770,26287,26465]
第一次查询为[2, 2][2,2]区间内的第一小值,即为6405
第二次查询为[3, 4][3,4]区间内的第一小值,即为15770
第三次查询为[4, 5][4,5]区间内的第一小值,即为26287
第四次查询为[1, 2][1,2]区间内的第二小值,即为25957
第五次查询为[4, 4][4,4]区间内的第一小值,即为26287
解题思路:
定义:主席树是一种可持久化的线段树 又叫函数式线段树
刚开始学是不是觉得很蒙逼啊 其实我也是
主席树说简单了 就是保留你每一步操作完成之后的线段树 然后有可加减性
呃 。。。 这么说好像还是有点生涩
那么就拿poj2104来举例子吧 慢慢讲我觉得会很好的
题意就是给你一个100000长度的数字 然后100000次询问[L,R]之间第k大的数字是多少
这个很容易看出来 暴力根本不可以 黑你分分钟的事情啊
我们怎么办呢 想想线段树能不能做 想来想去 一颗线段树好像不能这么做 GG
那么我们做一个美好的假设:
我们建立100000棵美丽的线段树 每一个线段树的节点 表示这一个区间内有多少个数字
第一棵线段树保存着把第一个数字插入进去之后 每个区间有多少个数字
第二棵线段树保存着把第一个 第二个数字插入进去之后 每个区间有多少个数字
。
。
。
。
第n棵线段树保存着把第1,2,3。。。。n个数字插入进去之后 每个区间有多少个数字
好了 我们已经建立了这么多的线段树 我们接下来该怎么办呢?
对 就是查询
可是如何查询呢? 假设我们要查询[l,r]内的第k大
我们可以拿出第l-1 ,r 棵线段树,然后两者相减 我们想一下 这样不就得到了相当于插入了第l到r个点所建立的一棵线段树 这棵线段树每个节点保留的信息是:这个区间内数字的个数 然后我们往下二分查找 就可以得到第k大了
现在的问题时 这么庞大的空间开销我们耗费不起 我们该如何建立这样的线段树呢?
答案就是 我们要尽量利用重复节点
我们可以想一下 我们每次建立线段树 相对于前一棵线段树 我们只修改了它的一条路径 最多只有logn的变化 那么我们就存下这logn的变化 尽可能的利用重复节点 就可以达到重复使用的目的
//原文:https://blog.csdn.net/qq_34271269/article/details/54849370
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#define maxn (int)(1e6+10) using namespace std; struct kkk {
int cnt,l,r;
}t[*maxn];
int init[maxn];
int cop[maxn];
int tc[maxn];
int n,tcnt = ,newn,m; void Discretization() {//离散化
sort(init,init+n);
newn = unique(init,init+n) - init;
for(int i = ;i < n; i++) cop[i] = lower_bound(init,init+n,cop[i]) - init;
} int add(int num,int bei,int l,int r) {
++tcnt;
t[tcnt].cnt = t[bei].cnt + ;
int save = tcnt;
int mid = (l + r) >> ;
if(l == r) {
return save;
}
else if(num <= mid) {
t[save].l = add(num,t[bei].l,l,mid);
t[save].r = t[bei].r;
}
else {
t[save].r = add(num,t[bei].r,mid + ,r);
t[save].l = t[bei].l;
}
return save;
} int chaxun(int x,int y,int k,int l,int r) {
if(l == r) return l;
int p = t[t[y].l].cnt - t[t[x].l].cnt;
int mid = (l + r) >> ;
if(k <= p)
return chaxun(t[x].l,t[y].l,k,l,mid);
else
return chaxun(t[x].r,t[y].r,k-p,mid + ,r);
} int main()
{
scanf("%d%d",&n,&m);
for(int i = ;i < n; i++) {
scanf("%d",&init[i]);
cop[i] = init[i];
}
Discretization();
for(int i = ;i <= n; i++) {
int p = add(cop[i-],tc[i-],,n);
tc[i] = p;
}
for(int i = ;i < m; i++) {
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
int ans = chaxun(tc[x-],tc[y],k,,n);
printf("%d\n",init[ans]);
}
return ;
}
POJ 2104 K-th Number && 洛谷 P3834 【模板】可持久化线段树 1(主席树)的更多相关文章
- 洛谷P3834 [模板]可持久化线段树1(主席树) [主席树]
题目传送门 可持久化线段树1(主席树) 题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定 ...
- 【洛谷 P3834】 可持久化线段树1(主席树)
题目链接 主席树=可持久化权值线段树. 如果你不会可持久化线段树,请右转 如果你不会权值线段树,请自行脑补,就是线段树维护值域里有多少个数出现. 可持久化线段树是支持查询历史版本的. 我们对每个数都进 ...
- 洛谷.3834.[模板]可持久化线段树(主席树 静态区间第k小)
题目链接 //离散化后范围1~cnt不要错 #include<cstdio> #include<cctype> #include<algorithm> //#def ...
- ☆ [洛谷P2633] Count on a tree 「树上主席树」
题目类型:主席树+\(LCA\) 传送门:>Here< 题意:给出一棵树.每个节点有点权.问某一条路径上排名第\(K\)小的点权是多少 解题思路 类似区间第\(K\)小,但放在了树上. 考 ...
- 洛谷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(主席树,树上差分)
题目链接 思维难度0 实现难度7 建出主席树后用两点的状态减去lca和lca父亲的状态,然后在新树上跑第\(k\)小 #include <cstdio> #include <cstr ...
- poj 2104 K-th Number 划分树,主席树讲解
K-th Number Input The first line of the input file contains n --- the size of the array, and m --- t ...
随机推荐
- 手动编译一个c文件(Win7下如何使用GCC编译器)
主要参考这篇http://jingyan.baidu.com/article/c275f6bacc0126e33c756771.html 我没找到minGW的下载地址,而是直接用codeblocks自 ...
- C#连接池
C#数据库连接池 MySql SqlServer 查阅了一天的资料来学习MySql数据库连接池,终于在一篇博文上找到了,自己也整理了一下,希望对大家有用处 1. 建立连接池 1 using MySql ...
- 光纤与PON基础概念整理
近期有幸接触到通讯这一领域,此文专门用于整理记录. 首先是光纤与光缆 光纤(OpticalFiber,OF)是用来导光的透明介质纤维,一根有用化的光纤是由多层透明介质构成,一般能够分为三部分:折射率 ...
- 在VC中动态加载ODBC的方法
在使用VC.VB.Delphi等高级语言编写数据库应用程序时,往往需要用户自己在控制面板中配置ODBC数据源.对于一般用户而言,配置ODBC数据源可能是一件比较困难的工作.而且,在实际应用中,用户往往 ...
- CentOS笔记-系统概述
Linux系统的启动过程并不是大家想象中的那么复杂,其过程可以分为5个阶段: 内核的引导. 当计算机打开电源后,首先是BIOS开机自检,按照BIOS中设置的启动设备(通常是硬盘)来启动. 操作系统接管 ...
- 百度自然语言处理api用法
def words url = "https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?access_token=1111111" param ...
- mysql字符串的常用函数(截取和拼接)
#截取字符串(先正序取2个,再倒序取1个)SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('aaa-gg-cc-dd','-',2),'-',-1) #获取子表某个字段的 ...
- linux 设备驱动程序中的一些关联性思考
首先,个人感觉设备驱动程序与应用程序中的文件操作隔得有点远,用户空间不论是直接使用系统调用还是库函数都是通过系统调用的接口进入内核空间代码的.但是看过一个博客的分析整个过程,感觉中间层太过麻烦,必须经 ...
- IE兼容模式
何为兼容模式 这个和IE的发展历程相关,在IE8之前Browser基本上属于IE一家独大,然后ie就有很多与web standard不一致的地方,比如只有自己才看得懂的tag等.后来由于chrome, ...
- Oracle dbf文件删除后,启动服务ORA-01157问题
有一个数据库硬盘空间满了,查看发现一个dbf超大,并且不在规定的路径下,知道是一个非重要数据文件,于是删除. 后来重启数据库时, SQL> startupORACLE instance star ...