区间第K小——可持久化线段树模板
概念
分析
sort + unique 进行离散化操作;然后以离散化后的元素作为底层(接下来大概就是用线段树按顺序记录每个数字出现的次数)。l..r 需要查询两个版本:ver[l-1]与ver[r],同步查询两棵树,并对查询到的内容相减便是l..r中该范围内的数据(以数字出现字数为关键词)。相当于线段树的前缀和。#include<bits/stdc++.h>
using namespace std; const int maxn = 2e5 + ;
int n, m, size_disc; //size_disc是离散化之后的长度
int n_init[maxn], n_disc[maxn]; //原数组 离散化后的数组
int rt[maxn], lc[maxn << ], rc[maxn << ], sum[maxn << ]; //rt:不同版本的根节点 lc/rc: 左儿子、右儿子(公用) sum: 和(公用)
int node_cnt, pnt_disc; //node总计数, pnt_disc: A中数字对应B中的值 void build(int& last_node, int l, int r)
{
last_node = ++ node_cnt;
sum[last_node] = ;
if(l == r) return;
int mid = (l + r) >> ;
build(lc[last_node], l, mid);
build(rc[last_node], mid+, r);
} int modify(int pre_rt, int l, int r)
{
int new_rt = ++node_cnt;
lc[new_rt] = lc[pre_rt];
rc[new_rt] = rc[pre_rt];
sum[new_rt] = sum[pre_rt] + ; int mid = (l + r) >> ;
if(l == r) return new_rt;
if(mid >= pnt_disc) lc[new_rt] = modify(lc[new_rt], l, mid);
else rc[new_rt] = modify(rc[new_rt], mid+, r);
return new_rt;
} int query(int rt1, int rt2, int k, int l, int r)
{
//printf("rt1:%d rt2:%d k:%d l:%d r:%d ", rt1, rt2, k, l, r);
if(l == r) return l;
int mid = (l + r) >> ;
int tmp = sum[lc[rt2]] - sum[lc[rt1]];
//int tmp=sum[lc[rt2]]-sum[lc[rt1]]; //printf("tmp:%d k:%d\n", tmp, k); int ans;
if(tmp >= k) ans = query(lc[rt1], lc[rt2], k, l, mid);
else ans = query(rc[rt1], rc[rt2], k-tmp, mid+, r);
return ans;
} void print_debug()
{
printf("node_cnt: %d\n", node_cnt);
for(int i = ;i <= node_cnt;i++)
printf("%d lc:%d rc:%d sum:%d\n", i, lc[i], rc[i], sum[i]);
} int main()
{
scanf("%d%d", &n, &m);
for(int i = ;i <= n;i++)
{
scanf("%d", &n_init[i]);
n_disc[i] = n_init[i];
}
sort(n_disc+, n_disc+n+); //先排序再进行离散化
size_disc = unique(n_disc+, n_disc+n+) - (n_disc+); node_cnt = ;
build(rt[], , size_disc);
for(int i = ;i <= n;i++)
{
pnt_disc = lower_bound(n_disc+, n_disc+size_disc+, n_init[i]) - n_disc; //改了1
rt[i] = modify(rt[i-], , size_disc); //只在上一个版本的基础上修改
} for(int i = ;i <m;i++)
{
int l, r, k;
scanf("%d%d%d", &l, &r, &k);l--;
int ans = query(rt[l], rt[r], k, , size_disc);
printf("%d\n", n_disc[ans]);
}
}
其中,遍历1~n建立n棵线段树的过程如下:

其中第i棵是建立在i-1棵的基础上,加上它们的n相同,结构也完全相同,两颗线段树相减就是这两个操作之间的变化值。
参考链接:
区间第K小——可持久化线段树模板的更多相关文章
- POJ- 2104 hdu 2665 (区间第k小 可持久化线段树)
可持久化线段树 也叫函数式线段树也叫主席树,其主要思想是充分利用历史信息,共用空间 http://blog.sina.com.cn/s/blog_4a0c4e5d0101c8fr.html 这个博客总 ...
- [POJ2104] 区间第k大数 [区间第k大数,可持久化线段树模板题]
可持久化线段树模板题. #include <iostream> #include <algorithm> #include <cstdio> #include &l ...
- 区间第k大问题 权值线段树 hdu 5249
先说下权值线段树的概念吧 权值平均树 就是指区间维护值为这个区间内点出现次数和的线段树 用这个加权线段树 解决第k大问题就很方便了 int query(int l,int r,int rt,int k ...
- 序列内第k小查询(线段树)
最近请教了一下大佬怎么求序列内第k大查询,自己又捣鼓了一下,虽然还没有懂得区间第k大查询,不过姑且做一个记录先吧 因为每个元素大小可能很大而元素之间不连续,所以我们先离散化处理一下,程序中的ori[ ...
- hdu 4417 区间内比h小的数 线段树
题意求区间内比h小的数的个数 将所有的询问离线读入之后,按H从小到大排序.然后对于所有的结点也按从小到大排序,然后根据查询的H,将比H小的点加入到线段树,然后就是一个区间和. 2015-07-27:专 ...
- 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 ...
- SPOJ Meteors - 可持久化线段树 - 二分法
Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The plan ...
- 洛谷P3834【模板】可持久化线段树 1(主席树)
题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...
- [DP][SA][可持久化线段树]黑红兔
源自 xyz32768 菜鸡的 FJ 省冬令营模拟赛题 原题 CF1063F Statement 给定一个长度为 \(n\) 的字符串 \(s\),仅包含小写英文字母 要从中从左往右选出若干段不相交的 ...
随机推荐
- Django-filter报错:__init__() got an unexpected keyword argument 'name'
原因是 自从 django-filter2.0之后 将Filter的name字段 更名为 field_name 所以需要这样写: class GoodsFilter(filters.FilterSet ...
- 【k8s第二步】Kubernetes-Kubeadm部署安装【已修正错误】
⒈开启kube-proxy的ipvs的前置条件 模式改为lvs调度的方式,kube-proxy主要解决的是svc(service)与pod之间的调度关系,ipvs的调度方式可以极大的增加它的访问效率, ...
- LC 349. Intersection of Two Arrays
题目描述 Given two arrays, write a function to compute their intersection. Example 1: Input: nums1 = [1, ...
- kmp跑两串的最大相同前后缀 HDU2594
题意:http://acm.hdu.edu.cn/showproblem.php?pid=2594 如题. 思路: Next数组记录的是pos位置失配时要跑到哪里,所以最后得再添加一个字符‘#’. 连 ...
- Python基础总结之第七天开始【认识函数的参数以及返回】(新手可相互督促)
周日的早上,吃的饱饱,刷刷抖音,开始学习新一天的知识了~~~ 函数的参数: 昨天的笔记中,我们已经使用了参数,在案例中的name和sex 就是参数. 一般的函数都是有参数的,函数的参数都是放在函数定义 ...
- 统计学习方法 | 感知机 | python实现
感知机是二类分类的线性分类模型,利用随机梯度下降法对基于误分类的损失函数进行极小化. 书中算法可以将所有样本和系数向量写成增广向量的形式,并将所有负样本乘以-1,统一形式,方便计算. (1)训练数据集 ...
- 怎样判断浏览器是否支持canvas
1. 如果网页必须使用canvas, 则需要告知用户更换或更新浏览器. 这时可以通过在<canvas>标签之间添加替代元素进行 <canvas id="c1"&g ...
- ArrayList插入1000w条数据的时间比较分析
一分钟系列: 读懂GC日志 ArrayList插入1000w条数据之后,我怀疑了jvm... Java JIT性能调优 Java性能优化指南系列(三):理解JIT编译器 准备:调试程序加入VM Opt ...
- select in关键字查询匹配多个字段
select id from table where (num,name) in ((num1,'name1'),(num2,'name2'))
- 使用.Net Core 2.2创建windows服务
使用.Net Core 2.2创建windows服务 我的环境 win 10 home Visual Studio 2019 v16.1.3 安装有.net core 2.2 创建项目 编辑项目文件 ...