区间第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\),仅包含小写英文字母 要从中从左往右选出若干段不相交的 ...
随机推荐
- 葡萄城首席架构师:前端开发与Web表格控件技术解读
讲师:Issam Elbaytam,葡萄城集团全球首席架构师(Chief Software Architect of GrapeCity Global).曾任 Data Dynamics.Inc 创始 ...
- FastJson 介绍
Json详解 Json是一种轻量级的数据交换格式,采用一种“键:值”对的文本格式来存储和表示数据,在系统交换数据过程中常常被使用,是一种理想的数据交换语言.在使用 Java 做 Web 开发时,不可避 ...
- HttpServletResponse对象(转)
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象.request和response对象即然代表请求和响应,那我们要 ...
- 如何判断你的windows系统是32位还是64位?
[学习笔记] 如 何判断你的windows系统是32位还是64位? java -version时,如果没有64就是32位的.eclipse.ini中如果没有64,就是32位的.但是我们的ini文件里面 ...
- LC 387. First Unique Character in a String
题目描述 Given a string, find the first non-repeating character in it and return it's index. If it doesn ...
- Graduation(思维,树上取叶子几次取完)
题意:https://codeforces.com/group/ikIh7rsWAl/contest/259944/problem/G 给你一颗树(可能有好几棵),你每次最多只能去掉k个叶子节点,问你 ...
- vim 插件 入门
vim 手册 vimtutor 精简版本 help user-manual 详细手册 一些vim自带设置 set nu "显示行号 set cursorline "高亮显示当前行 ...
- 一个复杂关联的sql
在项目中遇到了一个比较复杂关系的sql,关联关系有些模糊,现在梳理一下 sql如下: SELECT TRAN.TRANS_DATE, TRAN.TRANS_TIME, TRAN.BUSI_TRAC_C ...
- .Net C# RSA签名和验签重写
namespace com._80community.unittest.CUP { /// <summary> /// CUP Client /// </summary> pu ...
- java7:核心技术与最佳实践读书笔记——类加载
流程:class -> 加载 -> jvm虚拟机 -> 链接 . 一.类加载器概述 1.引出 类加载器也是一个java类,java.lang.ClassLoader类是所 ...