不修改的主席(HJT)树-HDU2665,POJ-2104;
参考:优秀的B站视频;
和 https://blog.csdn.net/creatorx/article/details/75446472
感觉主席树这个思路是真的优秀,每次在前一次的线段树的基础上建立一颗新的小线段树;所以更新和查询都是要前后两个根节点进行操作;
利用引用,只用修改此次的节点,而不动前一次的线段树;
主席树可用在求区间的第K大的数上:思路是:
我们也可以利用前缀和这个思想来解决建树这个问题,我们只需要建立n颗“前缀”线段树就行,第i树维护[1,i]序列,这样我们处理任意区间l, r时就可以通过处理区间[1,l - 1], [1,r],就行,然后两者的处理结果进行相加相减就行。为什么满足相加减的性质,我们简单分析一下就很容易得出。如果在区间[1,l - 1]中有x个数小于一个数,在[1,r]中有y个数小于那个数,那么在区间[l,r]中就有y - x 个数小于那个数了,这样就很好理解为什么可以相加减了,另外,每颗树的结构都一样,都是一颗叶节点为n个的线段树。
这里还有一个利用vector离散化的操作;
hdu ac的:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
#define pb push_back
const int maxn = ; struct node {
int l,r;
int sum;
}T[maxn*];
int a[maxn],root[maxn];
vector<int>v;
int getid(int x){
return lower_bound(v.begin(),v.end(),x) - v.begin() + ;
}
int n,m,cnt,x,y,k; void init(){
v.clear();
memset(T,,sizeof(T));
cnt = ;
}
void update(int l,int r,int &x,int y,int pos)
{
T[++cnt] = T[y]; T[cnt].sum++; x = cnt;
if(l==r)return;
int mid = (l+r)>>;
if(mid>=pos)
update(l,mid,T[x].l,T[y].l,pos);
else update(mid+,r,T[x].r,T[y].r,pos);
} int query(int l,int r,int x,int y,int pos)
{
if(l==r)return l;
int sum = T[T[y].l].sum - T[T[x].l].sum;
int mid = (l+r)>>;
if(sum >= pos)
return query(l,mid,T[x].l,T[y].l,pos);
else return query(mid+,r,T[x].r,T[y].r,pos - sum);
}
int main(){
int t;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&m);
for(int i=; i<=n; i++)
{
scanf("%d", &a[i]);
v.pb(a[i]);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(),v.end()),v.end()); for(int i=; i<=n; i++)
update(,n,root[i],root[i-],getid(a[i]));
for(int i=; i<=m; i++)
{
int le,ri,k;
scanf("%d%d%d", &le,&ri,&k);
printf("%d\n",v[query(,n,root[le-],root[ri],k)-]);
}
}
return ;
}
POJ的
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
#define pb push_back
const int maxn = ; struct node {
int l,r;
int sum;
}T[maxn*];
int a[maxn],root[maxn];
vector<int>v;
int getid(int x){
return lower_bound(v.begin(),v.end(),x) - v.begin() + ;
}
int n,m,cnt,x,y,k; void update(int l,int r,int &x,int y,int pos)
{
T[++cnt] = T[y]; T[cnt].sum++; x = cnt;
if(l==r)return;
int mid = (l+r)>>;
if(mid>=pos)
update(l,mid,T[x].l,T[y].l,pos);
else update(mid+,r,T[x].r,T[y].r,pos);
} int query(int l,int r,int x,int y,int pos)
{
if(l==r)return l;
int sum = T[T[y].l].sum - T[T[x].l].sum;
int mid = (l+r)>>;
if(sum >= pos)
return query(l,mid,T[x].l,T[y].l,pos);
else return query(mid+,r,T[x].r,T[y].r,pos - sum);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=; i<=n; i++)
{
scanf("%d", &a[i]);
v.pb(a[i]);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(),v.end()),v.end()); for(int i=; i<=n; i++)
update(,n,root[i],root[i-],getid(a[i]));
for(int i=; i<=m; i++)
{
int le,ri,k;
scanf("%d%d%d", &le,&ri,&k);
printf("%d\n",v[query(,n,root[le-],root[ri],k)-]);
} return ;
}
不修改的主席(HJT)树-HDU2665,POJ-2104;的更多相关文章
- HDU 2665.Kth number-可持久化线段树(无修改区间第K小)模板 (POJ 2104.K-th Number 、洛谷 P3834 【模板】可持久化线段树 1(主席树)只是输入格式不一样,其他几乎都一样的)
Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 主席树模板poj 2104
资料1:http://blog.csdn.net/regina8023/article/details/41910615 资料2:模板来源:http://www.cnblogs.com/lidaxin ...
- POJ 2104&HDU 2665 Kth number(主席树入门+离散化)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 50247 Accepted: 17101 Ca ...
- poj 2104 K-th Number 主席树+超级详细解释
poj 2104 K-th Number 主席树+超级详细解释 传送门:K-th Number 题目大意:给出一段数列,让你求[L,R]区间内第几大的数字! 在这里先介绍一下主席树! 如果想了解什么是 ...
- 主席树 【权值线段树】 && 例题K-th Number POJ - 2104
一.主席树与权值线段树区别 主席树是由许多权值线段树构成,单独的权值线段树只能解决寻找整个区间第k大/小值问题(什么叫整个区间,比如你对区间[1,8]建立一颗对应权值线段树,那么你不能询问区间[2,5 ...
- BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 7143 Solved: 2968[Su ...
- POJ 2104 K-th Number(主席树——附讲解)
Description You are working for Macrohard company in data structures department. After failing your ...
- Luogu Dynamic Ranking (带修改的主席树)
题目大意: 网址:https://www.luogu.org/problemnew/show/2617 给定一个序列a[1].a[2].....a[N],完成M个操作,操作有两种: [1]Q i j ...
- BZOJ2141排队——树状数组套权值线段树(带修改的主席树)
题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...
- POJ 2104 && POJ 2761 (静态区间第k大,主席树)
查询区间第K大,而且没有修改. 使用划分树是可以做的. 作为主席树的入门题,感觉太神奇了,Orz /* *********************************************** ...
随机推荐
- 原创:微信小程序开发要点总结
废话不多少,下面是对我从开发微信小程序的第一步开始到发布的总结,觉得对您有帮助的话,可以赞赏下,以对我表示鼓励. 一:首先注册登录微信公众平台,这个平台很重要,以后查文档全在上面看.https://m ...
- Spark Streaming自定义Receiver
一 背景 Spark社区为Spark Streaming提供了很多数据源接口,但是有些比较偏的数据源没有覆盖,由于公司技术栈选择,用了阿里云的MQ服务ONS,要做实时需求,要自己编写Receiver ...
- Asp.Net MVC SingleServiceResolver类剖析
SingleServiceResolver一般用于类工厂创建和注入点接口留白.类工厂创建比如Controller控制依赖于此类的创建,注入点留白实质上是依赖注入所对外预留的接口. 以第二个特性为例. ...
- TCP重置报文段及RST常见场景分析
RST表示连接重置,用于关闭那些已经没有必要继续存在的连接.一般情况下表示异常关闭连接,区别与四次分手正常关闭连接. 产生RST的三个条件是: 目的地为某端口的SYN到达,然而在该端口上并没有正在监听 ...
- for循环打印空心菱形的新方法
相信大家在学习流程控制的循环结构时,一定都用for循环绘制过菱形和空心菱形吧,我记得我当时写的很麻烦,把一个菱形分为上下两部分,上面2重for循环,下面2重for循环,相信有很多的小伙伴都是这样做的吧 ...
- bucket list 函数解析
cls_bucket_list 函数 librados::IoCtx index_ctx; // key - oid (for different shards if there is any) ...
- 缓存的有效期和淘汰策略【Redis和其他缓存】【刘新宇】
缓存有效期与淘汰策略 有效期 TTL (Time to live) 设置有效期的作用: 节省空间 做到数据弱一致性,有效期失效后,可以保证数据的一致性 Redis的过期策略 过期策略通常有以下三种: ...
- 1、JAVA的小白之路
大学的时光过得很快,转眼我已经大二了,在大一时,学习了C\C++,对于语言有一定基础,在未来的道路上,我需要攒足干劲,积累足够的知识和技能,去走上社会. 我的第一任大学班主任告诉我:“作为程序员,你至 ...
- LR(1)语法分析器生成器(生成Action表和Goto表)java实现(二)
本来这次想好好写一下博客的...结果耐心有限,又想着烂尾总比断更好些.于是还是把后续代码贴上.不过后续代码是继续贴在BNF容器里面的...可能会显得有些臃肿.但目前管不了那么多了.先贴上来吧hhh.说 ...
- Ubuntu 10.04下实现双网卡负载均衡
摘要:本文主要介绍和配置 在Ubuntu下 实现 bonding,双网卡负载,bonding模式为0,好处是负载平衡,另一网卡断了,也能工作. 什么是bonding Linux bonding 驱动提 ...