主席树 —— ②静态区间第K小

静态区间第K小

给出一段长度序列 a[1]、a[2]、… 、a[N],每次询问 [L, R] 区间内第K小的数为?

我们可以建立 权值线段树,线段树内存储 某个权值的出现次数

对于 [L, R] 区间(a[L] ~ a[R]),构建的线段树

以下示例参考blog:https://www.cnblogs.com/LiuRunky/p/Sustainable_Segment_Tree.html

例如:数列a={10,20,30,20,50,10,60,40},离散化后得到b={1,2,3,2,5,1,6,4}
对于数列内每一个离散化后的数,我们建立一个基于数值的 区间和线段树 统计它的出现次数
在这里插入图片描述
(7、8是用来占位的,可以无视)

这样,我们可以通过类似二分的思想找到第k小,而线段树的节点已经帮助我们将区间对半切分

假设我们想找区间第7小:

step 1: 区间[1,4]内的数一共出现了6次,所以我们可以直接进入另一区间[5,8],并且找这个区间中的第1小

step 2: 区间[5,6]内的数一共出现了2次,所以[5,8]中的第1小一定也是[5,6]中的第1小

step 3: 区间[5,5]内的数一共出现了1次,所以5正是[5,6]中的第1小,即整个查询区间中的第7小

那要怎么得到区间[L, R]的线段树呢,这里就要用到主席树,先建个出现次数全为0的空树,然后依次更新加入 a[1]、a[2]、… 、a[N],那我们就得到了N个版本的权值线段树(可以看作一个 树形的前缀和

对于任意一个结点,只需要用 第R个版本第L-1个版本 的线段树同位置结点相减,从L-1 到R这个结点增加的值,既是 [L, R]的线段树的值



模板题:POJ2104 - K-th Number

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e5+50;
int n,m,N,a[maxn],b[maxn],root[maxn];
int t[maxn<<5],ls[maxn<<5],rs[maxn<<5],cnt=0</
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值