首页 > 其他分享 >P3834 【模板】可持久化线段树 2

P3834 【模板】可持久化线段树 2

时间:2022-11-30 13:33:49浏览次数:72  
标签:rt leq int 线段 mid P3834 ls 模板

【模板】可持久化线段树 2

题目背景

这是个非常经典的可持久化权值线段树入门题——静态区间第 \(k\) 小。

数据已经过加强,请使用可持久化权值线段树。同时请注意常数优化

题目描述

如题,给定 \(n\) 个整数构成的序列 \(a\),将对于指定的闭区间 \([l, r]\) 查询其区间内的第 \(k\) 小值。

输入格式

第一行包含两个整数,分别表示序列的长度 \(n\) 和查询的个数 \(m\)。
第二行包含 \(n\) 个整数,第 \(i\) 个整数表示序列的第 \(i\) 个元素 \(a_i\)。
接下来 \(m\) 行每行包含三个整数 $ l, r, k$ , 表示查询区间 \([l, r]\) 内的第 \(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

提示

样例 1 解释

\(n=5\),数列长度为 \(5\),数列从第一项开始依次为\(\{25957, 6405, 15770, 26287, 26465\}\)。

  • 第一次查询为 \([2, 2]\) 区间内的第一小值,即为 \(6405\)。
  • 第二次查询为 \([3, 4]\) 区间内的第一小值,即为 \(15770\)。
  • 第三次查询为 \([4, 5]\) 区间内的第一小值,即为 \(26287\)。
  • 第四次查询为 \([1, 2]\) 区间内的第二小值,即为 \(25957\)。
  • 第五次查询为 \([4, 4]\) 区间内的第一小值,即为 \(26287\)。

数据规模与约定

  • 对于 \(20\%\) 的数据,满足 \(1 \leq n,m \leq 10\)。
  • 对于 \(50\%\) 的数据,满足 \(1 \leq n,m \leq 10^3\)。
  • 对于 \(80\%\) 的数据,满足 \(1 \leq n,m \leq 10^5\)。
  • 对于 \(100\%\) 的数据,满足 \(1 \leq n,m \leq 2\times 10^5\),\(|a_i| \leq 10^9\),\(1 \leq l \leq r \leq n\),\(1 \leq k \leq r - l + 1\)。

先看这篇博客

P3919 【模板】可持久化线段树 1(可持久化数组) - 沙野博士 - 博客园 (cnblogs.com)

本题要求查询区间第k小,也就是对于给定区间[l,r] ,将其中的数按从小到大排序,找到其中第k个元素。

由持久化线段树1可知,我们可以用线段树维护一个可持久化数组,这道题要维护的数组就是这些元素的桶这个数组。按位置每一个位置就是一个历史版本。

实现过程中,最好先建一个完整的空的线段树,省去判断指针是否为空的麻烦。

/*
P3834 【模板】可持久化线段树 2
*/
#include<algorithm>
#include<iostream>
using namespace std;
const int N = 2e5+10;
inline int read()
{
	register char c = getchar(); register int x = 0 , f = 0;
	while(c < '0' || c > '9') f |= c == '-' , c = getchar();
	while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
	return f ? -x : x;
}
int n;
int A[N] , B[N];
struct node{
	node *ls , *rs;
	int size;
	node(int size = 0) : ls(NULL) , rs(NULL) , size(size){}
}*rot[N];

void Init()
{
	//int *B = new int [n + 1];
	for(int i = 1 ; i <= n ; ++i) B[i] = A[i];
	sort(B + 1 , B + 1 + n);
	for(int i = 1 ; i <= n ; ++i) A[i] = lower_bound(B + 1 , B + 1 + n , A[i]) - B;
}

void build(node *&rt , int l , int r)
{
	rt = new node;
	if(l == r) return ;
	int mid = (l + r) >> 1;
	build(rt->ls , l , mid);
	build(rt->rs , mid+1 , r);
}

void modify(node *&rt , node *lst , int l , int r , int pos)
{
	rt = new node; rt->size = lst->size + 1;
	if(l == r) return ;
	int mid = (l + r) >> 1;
	if(pos <= mid)
		rt->rs = lst->rs , modify(rt->ls , lst->ls , l , mid , pos);
	else
		rt->ls = lst->ls , modify(rt->rs , lst->rs , mid+1 , r , pos);
}

int query(node *L , node *R , int l , int r , int k)
{
	if(l == r) return l;
	int num = (R->ls ? R->ls->size : 0) - (L->ls ? L->ls->size : 0);
	int mid = (l + r) >> 1;
	if(k <= num)
		return query(L->ls , R->ls , l , mid , k);
	else
		return query(L->rs , R->rs , mid+1 , r , k - num);
}

int main()
{
	int m , l , r , k;
	n = read(); m = read();
	for(int i = 1 ; i <= n ; ++i)
		A[i] = read();
	Init();
	// cout << "YES" << '\n';
	build(rot[0] , 1 , n);
	// cout << "YES" << '\n';
	for(int i = 1 ; i <= n ; ++i)
		modify(rot[i] , rot[i-1] , 1 , n , A[i]);
	// cout << "YES" << '\n';
	while(m--)
	{
		l = read(); r = read(); k = read();
		printf("%d\n" , B[query(rot[l-1] , rot[r] , 1 , n , k)]);
	}
	return 0;
}

标签:rt,leq,int,线段,mid,P3834,ls,模板
From: https://www.cnblogs.com/sybs5968QAQ/p/16938124.html

相关文章

  • 二叉树模板套题——相同的树的应用
    (文章目录)力扣100.相同的树给你两棵二叉树的根节点p和q,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。......
  • SpringMVC创建JSP页面的详细过程+配置模板+实现页面跳转+配置Tomcat。JSP和HTML配置模
    1、创建Maven项目2、填写项目基本信息、完成创建3、导入POM依赖打包方式设置为War包<packaging>war</packaging>依赖、可自行添加需要jar包依赖<dependencies>......
  • 【视频教程】帝国CMS制作网站系列教程14—标签模板及标签讲解
    作为一个程序员,搭建一个自己的博客网站是件非常容易的事情,但是作为很多非程序员非计算机专业的学习者来讲,可能就需要花点时间进行学习,而如果你想通过自学来学习怎么制作一个......
  • 【视频教程】帝国CMS制作网站系列教程13—全站全文搜索及模板
    作为一个程序员,搭建一个自己的博客网站是件非常容易的事情,但是作为很多非程序员非计算机专业的学习者来讲,可能就需要花点时间进行学习,而如果你想通过自学来学习怎么制作一个......
  • 帝国CMS:如何根据访客不同展示不同的首页模板?
    需求描述:当我们需要进行备案时,不想关站但又想进行备案审核,那么我们就可以根据访客的不同,来展示不同的模板。可以暂定为,人访问给出备案中提示的模板;而搜索引擎的蜘蛛爬行......
  • 归并排序模板
    归并排序模板归并排序要点:分治的思想确定分界点mid=(l+r)/2;递归排序left,right归并——合二为一(归并排序的核心)#include<bits/stdc++.h>usingnamespac......
  • WPF控件模板(6)
    什么是ControlTemplate?ControlTemplate(控件模板)不仅是用于来定义控件的外观、样式,还可通过控件模板的触发器(ControlTemplate.Triggers)修改控件的行为、响应动画等......
  • C++——多层嵌套模板类的静态成员变量的声明与定义方式
    在C++类的设计中,静态成员变量必须在类中声明,在类外定义,对于模板类亦是如此。如果只是单层级的模板类,其声明方式参考如下代码:template<typenameupid_t>classparent......
  • Discuz模板制作视频教程
    资源简介discuz的模板也是可以自己制作的,想让你的网站更好看,更适合你的论坛主题,那就来学习一下怎么做模板吧。discuz模板制作视频教程,只需要简单的9节课,就能轻松教会大家......
  • 【小航的算法日记】线段树
    本内容取经于:https://leetcode.cn/problems/my-calendar-i/solution/by-lfool-xvpv/一、概念概念区分:线段树解决的是「区间和」的问题,且该「区间」会被修改前缀和解决的是......