poj 2104: K-th Number 【主席树】
学习了一下主席树,感觉具体算法思路不大好讲。。
大概是先建个空线段树,然后类似于递推,每一个都在前一个“历史版本”的基础上建立一个新的“历史版本”,每个历史版本只需占用树高个空间(好神奇!)
查询时这道题是通过“历史版本”间作差解决
*另外提一下,在建立“历史版本”的过程中,是“新建”,而不是“更新”,是先copy过来原有的,再按个人需求改成自己的,所产生的一个新的“历史版本”
希望注释能有帮助
//吐槽一下,本人看kuangbin模板看得好费劲,一方面不习惯用lson[],rson[]数组搞线段树,另一方面他的update query函数都是用二分写的,看半天没理解。。。
以下是按个人习惯加了注释的代码
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#define M 100000+5
using namespace std; const int N=1e5+;
const int INF=0x3f3f3f3f; struct node
{
int l,r; //l,r分别指向左右孩子,但由于历史的错乱,二者的值未必有规律
int size; //当前历史版本里,该节点中所包含的元素个数
//p.s. 在最后一个历史版本里,size即为总元素个数n
}tr[N*];
//主席树的初始状态为一“空架子”
//每次updata都在前一“历史版本”基础上新建h个结点,共updata n次,产生了n个历史版本,每个版本占用空间为h*sizeof(one node)
int tot; //结点建立顺序|所赋标号 int n; //共n个数
int a[N]; //读入数组
int root[N];//记录a[]中每一个数对应各“历史版本”在主席树中的根结点标号
int m; //t[]中元素个数
int t[N]; //离散数组
int pos(int x)
{
return lower_bound(t+,t++m,x)-t;
}
int q; //q个询问 int build(int l,int r)
{
int rt=tot++;
tr[rt].size=;
if(l==r) return rt;
int mid=(l+r)>>;
tr[rt].l=build(l,mid);
tr[rt].r=build(mid+,r);
return rt;
} // pre_node:最近一历史,[l,r]当前所更新到的包含x的区间
// x此次更新的“终点”
// 沿途要增加的“权值”
// p.s. 1<=l<=r<=m
int updata(int pre_node,int l,int r,int x,int v)
{
int rt=tot++; //rt为新结点的标号
tr[rt]=tr[pre_node]; //先拷贝原指向当前区间的结点
tr[rt].size+=v;
// 在函数不断向下深入过程中,更新node.size
if(l==r) return rt;
int mid=(l+r)>>;
if(x<=mid) tr[rt].l=updata(tr[pre_node].l,l,mid,x,v);
else tr[rt].r=updata(tr[pre_node].r,mid+,r,x,v);
return rt;
// 在函数逐步return过程中,更新node.l|r
} // ql,qr反应的是在a[]中的下标,对应着更新到该下标时的“历史版本”
// l,r反应的是在t[]中的下标
int query(int ql,int qr,int l,int r,int k)
{
if(l==r) return l;
int diff=tr[tr[qr].l].size-tr[tr[ql].l].size;//在更新到ql位置和更新到qr位置时两个“历史版本”下左孩子的size之差
// p.s. size的大小反应较小数的多少
int mid=(l+r)>>;
if(diff>=k) return query(tr[ql].l,tr[qr].l,l,mid,k);
else return query(tr[ql].r,tr[qr].r,mid+,r,k-diff);
}
int main()
{
while(~scanf("%d%d",&n,&q))
{
for(int i=;i<=n;i++)
scanf("%d",&a[i]),t[i]=a[i];
sort(t+,t++n);
m=unique(t+,t++n)-t-;
m++,t[m]=INF;
tot=;
root[]=build(,m); //初始化一个空线段树
for(int i=;i<=n;i++)
{
int order=pos(a[i]);
root[i]=updata(root[i-],,m,order,);
//每次在上一次已完成的基础上新增h个结点
//从根 逐步新建结点到 a[i]在线段树上所对应的位置
//在这个逐步新建结点的过程中,要新建的结点的l,r始终满足l<=m<=r
//这些结点每一个的size都在pre_node的基础上+1
}
while(q--)
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",t[query(root[l-],root[r],,m,k)]);
}
}
}
poj 2104: K-th Number 【主席树】的更多相关文章
- 【POJ 2104】 K-th Number 主席树模板题
达神主席树讲解传送门:http://blog.csdn.net/dad3zz/article/details/50638026 2016-02-23:真的是模板题诶,主席树模板水过.今天新校网不好,没 ...
- 静态区间第k大(主席树)
POJ 2104为例(主席树入门题) 思想: 可持久化线段树,也叫作函数式线段树,也叫主席树(高大上). 可持久化数据结构(Persistent data structure):利用函数式编程的思想使 ...
- poj 2104 K-th Number 主席树+超级详细解释
poj 2104 K-th Number 主席树+超级详细解释 传送门:K-th Number 题目大意:给出一段数列,让你求[L,R]区间内第几大的数字! 在这里先介绍一下主席树! 如果想了解什么是 ...
- poj2104 k-th number 主席树入门讲解
poj2104 k-th number 主席树入门讲解 定义:主席树是一种可持久化的线段树 又叫函数式线段树 刚开始学是不是觉得很蒙逼啊 其实我也是 主席树说简单了 就是 保留你每一步操作完成之后 ...
- POJ 2104 K-th Number 主席树(区间第k大)
题目链接: http://poj.org/problem?id=2104 K-th Number Time Limit: 20000MSMemory Limit: 65536K 问题描述 You ar ...
- POJ 2104:K-th Number(主席树静态区间k大)
题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var ...
- POJ 2104 K-th Number ( 求取区间 K 大值 || 主席树 || 离线线段树)
题意 : 给出一个含有 N 个数的序列,然后有 M 次问询,每次问询包含 ( L, R, K ) 要求你给出 L 到 R 这个区间的第 K 大是几 分析 : 求取区间 K 大值是个经典的问题,可以使用 ...
- SPOJ MKTHNUM & POJ 2104 - K-th Number - [主席树模板题]
题目链接:http://poj.org/problem?id=2104 Description You are working for Macrohard company in data struct ...
- poj 2104 K-th Number(主席树 视频)
K-th Number 题意: 给你一些数,让你求一个区间内,第k大的数是多少. 题解: 主席树第一题,看的qsc视频写的,戳戳戳 学到了unique函数,他的作用是:把相邻的重复的放到后面,返回值是 ...
- Poj 2104 K-th Number(主席树&&整体二分)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Case Time Limit: 2000MS Description You are wor ...
随机推荐
- BeautifulSoup笔记
## find_all的使用: 1. 在提取标签的时候,第一个参数是标签的名字.然后如果在提取标签的时候想要使用标签属性进行过滤,那么可以在这个方法中通过关键字参数的形式,将属性的名字以及对应的值传进 ...
- 'utf-8-sig api_res = r.data.decode('utf-8') json_ = json.loads(api_res)
东莞市 东莞城市标志 东莞城市标志 1985年,广东省东莞县经国务院批准列为珠江三角洲经济开发区,同年9月撤消东莞县,建立(县级)东莞市,1988年1月升格为地级市.东莞市是全国五个不设市辖区的地级市 ...
- js 数组相减 (一个数组去掉不符合条件的子数组)
数组相减?我也希望将来在ES8或者更好js版本能带来数组之间相互运算的方法,但是现在不能,咱们只能靠已有的方法实现: var arr1 = [2,3,5,88,99,444,66],arr2 = [2 ...
- HTML-lang属性规定元素内容的语言
所有浏览器均支持 lang 属性. 属性lang是英语language的缩写,意思是语言,”en”代表英语,”zh-CN”代表中文 注释:lang 属性在以下标签中无效:<base>, & ...
- css设计丝带
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8&quo ...
- Buy Tickets 【POJ - 2828】【线段树】
题目链接 有N次操作,每次都是将第i个数放置在第pos个数的后面,并且这个数的值是val. 这个线段树的思维确实很好,我们可以发现,后面放进去的数,一定是强制位置的,而前面放的数,会随着后面的数进入而 ...
- (转载)Manacher'sAlgorithm: O(n)时间求字符串的最长回文子串
以下内容转载自:传送门 源于这两篇文章: http://blog.csdn.net/ggggiqnypgjg/article/details/6645824http://zhuhongcheng.wo ...
- 20190823 尚硅谷MySQL核心技术
背景 视频时间:2017.09 MySQL版本:5.5 MySQL基础 命令行启动.停止MySQL: net start MySQL(这里是注册的服务名称) net stop MySQL 命令行连接M ...
- Linux安装redis服务器和部署
Linux安装redis和部署 第一步:下载安装包 wget http://download.redis.io/releases/redis-5.0.5.tar.gz 访问https://redis. ...
- python 分析 知乎粉丝数据
昨天花了一下午写了一个小爬虫,用来分析自己的粉丝数据.这个真好玩!今天帮了群里好多大V也爬了他们的数据.运行速度:每分钟5千粉丝以上.暂时先写成这样,这两天要准备补考,没有时间继续玩这个. 下次要改进 ...