题目背景

这是个非常经典的主席树入门题——静态区间第K小

数据已经过加强,请使用主席树。同时请注意常数优化

题目描述

如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值。

输入输出格式

输入格式:

第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。

第二行包含N个整数,表示这个序列各项的数字。

接下来M行每行包含三个整数l, r, kl,r,k , 表示查询区间[l, r][l,r]内的第k小值。

输出格式:

输出包含k行,每行1个整数,依次表示每一次查询的结果

输入输出样例

输入样例#1: 复制

5 5
25957 6405 15770 26287 26465
2 2 1
3 4 1
4 5 1
1 2 2
4 4 1
输出样例#1: 复制

6405
15770
26287
25957
26287

题面非常清晰,区间第k大。首先,每次排序再还原肯定是要跪的。

这时主席树就出现了。

主席树,倒不如说是榕树(有多个根节点,但是却不是森林)。可以说是在用空间换时间。

其实这题,主席树的主体应该是一棵权值线段树。

别人都说主席树是在每个位置维护了一颗线段树,我一直以为是每一个叶节点,其实是在每一个...好吧就是叶节点。

这里可能要把历史值那一题拿出来讲讲,主席树的每一次修改只修改一条链,而不是整个换血,所以为我们的查询提供了方便。

模拟一发:

7 1

1 5 2 6 3 7 4

建树:(感谢@bestFy的数据和图!)


插完所有的之后:

(妥妥的权值线段树)

最终图只是最后一棵线段树的样子,之前的各个线段树依旧在保存着。

于是就出现了旧节点和新建的节点公用一个根节点的情况。于是就可以愉快地进行差分了(因为两个新旧节点是等价的啊)

∴两棵线段树的对应节点相减就是对应区间有的数字啦

所以对于一个区间[l, r],我们可以每次算出在[l, mid]范围内的数,如果数量>=k(k就是第k大),就往左子树走,否则就往右子树走。

于是区间第k大就完成了。

贴代码:

#include<bits/stdc++.h>
变量解释:sum:节点的总数
rt:新旧树的根节点
ls:左儿子
rs:右儿子
tot:当前节点编号
using namespace std;
const int maxn=;
int n,m,tot,sum[maxn<<],rt[maxn<<],ls[maxn<<],rs[maxn<<],a[maxn],b[maxn],len; int build(int l,int r)
{
int root=++tot;//每新建一个节点(根)
if(l==r) return root;//如果到叶节点了返回根的值,我们要记录下来
int mid=l+r>>;//二分区间
ls[root]=build(l,mid);//记录下一层的根,也就是左儿子
rs[root]=build(mid+,r);//同上
return root;//返回大根
}
int updata(int l,int r,int root,int k)
{
int newroot=++tot;//新建的根的编号
ls[newroot]=ls[root];//记录
rs[newroot]=rs[root];//建一个等价的节点,左右儿子也是旧根节点的左右儿子
sum[newroot]=sum[root]+;//每新建一条链增加一个有值的点,所以+1(权值线段树)
if(l==r) return newroot;
int mid=l+r>>;
if(k<=mid) ls[newroot]=updata(l,mid,ls[newroot],k);//
else rs[newroot]=updata(mid+,r,rs[newroot],k);
return newroot;
}
int query(int fl,int fr,int l,int r,int k)
{
int mid=l+r>>,x=sum[ls[fr]]-sum[ls[fl]];//查询区间里的东西,先遍历左儿子,不行再往右跑
if(l==r) return l;
else if(k<=x) return query(ls[fl],ls[fr],l,mid,k);//差分了
else return query(rs[fl],rs[fr],mid+,r,k-x);//差分了
}
int main()
{
int i,x,l,r,k;
scanf("%d%d",&n,&m);
for(i=;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+,b++n);
len=unique(b+,b++n)-b-;//去重,神仙操作
//printf("%d\n",len);
rt[]=build(,len);//根的“tot”(下标,第几个点)
for(i=;i<=n;i++)//要对每一个节点建树,所以n次加边
{
x=lower_bound(b+,b++len,a[i])-b;//离散化,更新相对大小,也就是把所有数的编号弄小
rt[i]=updata(,len,rt[i-],x);//新根的编号
}
for(i=;i<=m;i++)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",b[query(rt[l-],rt[r],,len,k)]);//query返回的是下标,所以要这么长一串。。
}
for(int i=;i<=*n;i++)
{
//if(sum[i]==0)break;
printf("%d ",sum[i]);
}
return ;
}

(完)


主席树学习笔记(静态区间第k大)的更多相关文章

  1. ZOJ -2112 Dynamic Rankings 主席树 待修改的区间第K大

    Dynamic Rankings 带修改的区间第K大其实就是先和静态区间第K大的操作一样.先建立一颗主席树, 然后再在树状数组的每一个节点开线段树(其实也是主席树,共用节点), 每次修改的时候都按照树 ...

  2. 线段树专题2-(加强版线段树-可持续化线段树)主席树 orz! ------用于解决区间第k大的问题----xdoj-1216

    poj-2104(区间第K大问题) #include <iostream> #include <algorithm> #include <cstdio> #incl ...

  3. 可持久化线段树(主席树)——静态区间第k大

    主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...

  4. HDU3473--Minimum Sum(静态区间第k大)

    Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  5. poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板

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

  6. 主席树(静态区间第k大)

    前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...

  7. 静态区间第k大(归并树)

    POJ 2104为例 思想: 利用归并排序的思想: 建树过程和归并排序类似,每个数列都是子树序列的合并与排序. 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数, ...

  8. 主席树初步学习笔记(可持久化数组?静态区间第k大?)

    我接触 OI也快1年了,然而只写了3篇博客...(而且还是从DP跳到了主席树),不知道我这个机房吊车尾什么时候才能摸到大佬们的脚后跟orz... 前言:主席树这个东西,可以说是一种非常畸形的数据结构( ...

  9. HDU 2665 Kth number(主席树静态区间第K大)题解

    题意:问你区间第k大是谁 思路:主席树就是可持久化线段树,他是由多个历史版本的权值线段树(不是普通线段树)组成的. 具体可以看q学姐的B站视频 代码: #include<cmath> #i ...

随机推荐

  1. 你真的懂Spring Java Config 吗?Full @Configuration vs lite @Bean mode

    Full @Configuration和lite @Bean mode 是 Spring Java Config 中两个非常有意思的概念. 先来看一下官方文档关于这两者的相关内容: The @Bean ...

  2. MySQL 视图(合并多表数据)引发的严重性能问题

    问题背景: 一.客户环境连续多次出现性能问题,系统登入异常,数据库CPU告警. 处理过程: 1>协助排查数据库性能问题时发现如下两个较频繁的SQL导致严重的性能问题(均使用了视图合并多表数据): ...

  3. A-08 拉格朗日对偶性

    目录 拉格朗日对偶性 一.原始问题 1.1 约束最优化问题 1.2 广义拉格朗日函数 1.3 约束条件的考虑 二.对偶问题 三.原始问题和对偶问题的关系 3.1 定理1 3.2 推论1 3.3 定理2 ...

  4. 使用Spring-boot-starter标准改造项目内的RocketMQ客户端组件

    一.背景介绍 我们在使用Spring Cloud全家桶构建微服务应用时,经常能看到spring-boot-xxx-starter的依赖,像spring-boot-starter-web.spring- ...

  5. 机器学习实战_KNN(一)

    [是什么] KNN 即 k_近邻算法(k- nearest neighbor) ,就是寻找K个邻居作为该样本的特征,近朱者赤,近墨者黑,你的邻居是什么特征,那么就认为你也具备该特征:核心公式为: 数据 ...

  6. wireshark分析https

    0x01 分析淘宝网站的https数据流 打开淘宝 wireshark抓取到如下 第一部分: 因为https是基于http协议上的,可以看到首先也是和http协议一样的常规的TCP三次握手的连接建立, ...

  7. jar包的多层级maven依赖的坑与正确传递方法

    这个问题简述起来就是项目加载jar包但是无法加载jar包的依赖 这是一个maven的特性吗? 问题发生前 程序猿经常自己写一些库实现或收集常用的逻辑方法(算法和设计模式等等),以方便多个项目使用,避免 ...

  8. docker2-容器的使用

    [root@ipha-dev71- chenjl]# docker [root@ipha-dev71- chenjl]# docker pull training/webapp [root@ipha- ...

  9. Java代码性能优化的 39个细节

    在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重要,能够显著地提升程序性能. 1:在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提 ...

  10. maven 打包 spring boot 生成docker 镜像

    1.所使用材料 ,spring boot 项目 基于maven ,maven 工具, docker工具 ps:为啥使用 docker 公司微服务需要启动太多,有两个优点吧! 1.方便管理,2.减少服务 ...