参考:优秀的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;的更多相关文章

  1. 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 ...

  2. 主席树模板poj 2104

    资料1:http://blog.csdn.net/regina8023/article/details/41910615 资料2:模板来源:http://www.cnblogs.com/lidaxin ...

  3. POJ 2104&HDU 2665 Kth number(主席树入门+离散化)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 50247   Accepted: 17101 Ca ...

  4. poj 2104 K-th Number 主席树+超级详细解释

    poj 2104 K-th Number 主席树+超级详细解释 传送门:K-th Number 题目大意:给出一段数列,让你求[L,R]区间内第几大的数字! 在这里先介绍一下主席树! 如果想了解什么是 ...

  5. 主席树 【权值线段树】 && 例题K-th Number POJ - 2104

    一.主席树与权值线段树区别 主席树是由许多权值线段树构成,单独的权值线段树只能解决寻找整个区间第k大/小值问题(什么叫整个区间,比如你对区间[1,8]建立一颗对应权值线段树,那么你不能询问区间[2,5 ...

  6. BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7143  Solved: 2968[Su ...

  7. POJ 2104 K-th Number(主席树——附讲解)

    Description You are working for Macrohard company in data structures department. After failing your ...

  8. Luogu Dynamic Ranking (带修改的主席树)

    题目大意: 网址:https://www.luogu.org/problemnew/show/2617 给定一个序列a[1].a[2].....a[N],完成M个操作,操作有两种: [1]Q i j ...

  9. BZOJ2141排队——树状数组套权值线段树(带修改的主席树)

    题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...

  10. POJ 2104 && POJ 2761 (静态区间第k大,主席树)

    查询区间第K大,而且没有修改. 使用划分树是可以做的. 作为主席树的入门题,感觉太神奇了,Orz /* *********************************************** ...

随机推荐

  1. Djangou中使用cookie和session

    一.会话跟踪 我们先需要了解是什么是会话!可以把会话理解为客户端与服务器之间的一次会话,在一次会话中可能会包含多次请求和响应,例如你给10086打个电话,你就是客户端,而10086服务人员就是服务器, ...

  2. @Validated和@Valid的区别?校验级联属性(内部类)

    每篇一句 NBA里有两大笑话:一是科比没天赋,二是詹姆斯没技术 相关阅读 [小家Java]深入了解数据校验:Java Bean Validation 2.0(JSR303.JSR349.JSR380) ...

  3. Maven项目的打包发布到Nexus私服和服务器

    1.编写pom文件如下: <build> <plugins> <plugin> <groupId>org.apache.maven.plugins< ...

  4. git之coding.net的使用

    先在Coding上创建个项目     现在是这样,我本地有个项目Project(/Users/huang/Desktop/Project),我想把它上传到刚创建的项目里,以后就用git代码托管.可我之 ...

  5. IO流与NIO流

    JAVA IO流最详解   (转自CSDN) IO流上:概述.字符流.缓冲区(java基础)   一.IO流概述 概述: IO流简单来说就是Input和Output流,IO流主要是用来处理设备之间的数 ...

  6. Linux下,为应用程序添加桌面图标(ubuntu18.4)

    一.桌面图标位置 Lniux下桌面图标储存路径为:/usr/share/applications 二.桌面图标格式 所有桌面图标格式均为desktop,即名为XXX.desktop 三.编辑内容(常用 ...

  7. 禅道、jenkins部署记录

    禅道部署1.检查你linux系统的位数(uname -a)2.下载对应位数的禅道包3.通过xftp工具将禅道包拷贝到虚拟机的/opt目录4.tar 对禅道包进行解压5.改配置:vi /opt/zbox ...

  8. 算法与数据结构基础 - 排序(Sort)

    排序基础 排序方法分两大类,一类是比较排序,快速排序(Quick Sort).归并排序(Merge Sort).插入排序(Insertion Sort).选择排序(Selection Sort).希尔 ...

  9. 项目构建分析和 webpack 优化实践

    加入新公司一个月,最近接手在做一个 chrom 浏览器插件的项目,开发过程中发现项目打包的时间很长,足足有30多秒,这是让人很难接受的,而且构建的显示了几条包体积过大的提示信息: 可以看到,打包后有三 ...

  10. Jenkins持续集成项目搭建——基于Python Selenium自动化测试

    参考链接:https://www.liaoxuefeng.com/article/1083282007018592 第一步:去官网https://jenkins.io/下载最新的war包 第二步:安装 ...