首页 > 其他分享 >可持久化线段树

可持久化线段树

时间:2023-10-25 19:23:06浏览次数:28  
标签:ch 持久 int 线段 tr rk define

可持久化线段树

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

特点:支持查询线段树的历史版本

实现:每次修改只涉及\(log_2N\)个点,所以每次修改就先复制上一个状态,然后修改涉及到的一条链即可,时间复杂度\(O(Nlog^2N)\)(修改因为要离散化,是双log;查询单log)

注意要保留每个状态的root,左右儿子的define,线段树的赋值,查询时要先试左儿子够不够……

#include<bits/stdc++.h>
#define mid (l+r>>1)
#define ls tr[i].ch[0]
#define rs tr[i].ch[1]
#define lc tr[j].ch[0]
#define rc tr[j].ch[1]
using namespace std;
const int N=2e5+5;
struct node{
	int num,ch[2];
}tr[N*20];
int n,m,a[N],rk[N],idx=0,cnt,rt[N];
inline void upd(int i,int &j,int l,int r,int k){
	j=++idx; tr[j]=tr[i]; tr[j].num++;
	if(l==r) return ;
	if(k<=mid) upd(ls,lc,l,mid,k);
	else upd(rs,rc,mid+1,r,k);
} 
inline int qry(int i,int j,int l,int r,int k){
	if(l==r) return l;
	int s=tr[lc].num-tr[ls].num;
	if(k<=s) return qry(ls,lc,l,mid,k);
	else return qry(rs,rc,mid+1,r,k-s);
}
int main(){
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin>>n>>m; for(int i=1;i<=n;++i) cin>>a[i],rk[i]=a[i];
	sort(rk+1,rk+n+1); cnt=unique(rk+1,rk+n+1)-(rk+1);
	for(int i=1;i<=n;++i) upd(rt[i-1],rt[i],1,cnt,lower_bound(rk+1,rk+cnt+1,a[i])-rk);
	int i,j,k;
	while(m--){
		cin>>i>>j>>k;
		cout<<rk[qry(rt[i-1],rt[j],1,cnt,k)]<<'\n';
	}
	return 0;
}

标签:ch,持久,int,线段,tr,rk,define
From: https://www.cnblogs.com/superl61/p/17787940.html

相关文章

  • 算法笔记(1)线段树
    原发表于个人博客。前言线段树,是数据结构皇冠上的明珠(我编的)。它用途广泛,被一代代的oier应用,改进,优化。本文介绍了线段树的基础知识和各种拓展(包括权值线段树,可持久化线段树),各种优化方式(包括zkw线段树,动态开点,离散化),希望能帮到更多的oier。在学习线段树前,默认你应该学会一下......
  • 【学习笔记】线段树合并
    前置知识:动态开点权值线段树。线段树合并,顾名思义,就是将两棵权值线段树合并在一起。为什么不把两棵普通的线段树合并呢?因为那样好像没啥用。我们知道,权值线段树支持着查询某个数的个数、查询第\(k\)大/小的数等操作,有了合并操作之后就可能会支持一些令人意想不到的操作。放张......
  • P3373 【模板】线段树 2
    【模板】线段树2如题,已知一个数列,你需要进行下面三种操作:将某区间每一个数乘上\(x\);将某区间每一个数加上\(x\);求出某区间每一个数的和。输入格式第一行包含三个整数\(n,q,m\),分别表示该数列数字的个数、操作的总个数和模数。第二行包含\(n\)个用空格分隔的整数,其中第\(i\)......
  • T125847 【模板】动态开点线段树
    \(T125847\)题目背景注意:请注意时间限制是800ms请使用较快的输入输出注意:空间限制是128MB请不要开longlong时限在std的2.5倍以上题目描述有一个有\(1000000000\)个数的初始值全为\(0\)的区间,你要进行两种操作:将某区间每一个数加上 \(x\)求出某区间每一个数的和输入格式第一行包......
  • Redis 数据持久化
    Redis支持两种数据持久化方式:RDB方式和AOF方式。前者会根据配置的规则定时将内存中的数据持久化到硬盘上,后者则是在每次执行写命令之后将命令记录下来。两种持久化方式可以单独使用,但是通常会将两者结合使用。一、持久化1.1、什么是持久化持久化功能有效地避免因进程退出造成的......
  • 算法学习笔记(31): 李超线段树
    李超线段树是一种按照值域维护一次函数最值的数据结构,其核心在于一次函数和值域的双单调性。如果预先对于值域离散也可以维护其最值。也就是说只要满足时一次函数,以及下标的单调性都可以利用李超线段树维护。李超线段树就是利用线段树来维护一次函数的最值,每一个结点对应了一......
  • 962. 最大宽度坡(权值线段树, 权值树状数组)
     本题要快速找到某个数字在数组中左边<=它的数的最小下标。可以建立一个权值线段树,nums[i]处维护最小下标。classSolution{public:conststaticintN=50010,INF=0x3f3f3f3f;structNode{intl,r,v;}tr[N*4];voidpushup(int......
  • redis 持久化
    2.1.基于AOF的持久化机制Redis的AOF持久化是指将数据存储到二进制日志文件中,以便在重启或出现故障时可以恢复数据。AOF持久化会周期性地将数据写入到日志文件中,因此可以实现更高的数据备份频率。 2.2.基于RDB的持久化机制基于RDB的持久化方式会把当前内存中所有Redis键值对......
  • 点到线段的距离
    情况1情况2情况3情况4 publicstaticfloatPointToLineSegmentDistance(Vector2P,Vector2A,Vector2B){floata=Vector2.Distance(A,B);floatb=Vector2.Distance(A,P);floatc=Vector2.Distance(B,P);if(b<=float.MinValue||......
  • 线段树练习
    习题都来自董老师的博客和b站:LuoguP4198楼房重建其实这道题的思路肯定是用线段树,但是为了计算结果线段树需要维护哪些信息?//mx表示区间内的最大斜率,sum表示区间内可见的,主要就是递归求出sum#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#inclu......