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

可持久化线段树

时间:2024-10-11 16:43:27浏览次数:8  
标签:持久 rs int 线段 num ls 版本

可持久化线段树

P3919 【模板】可持久化线段树 1(可持久化数组)

维护一个长度为 \(N\) 的数组,支持如下几种操作

  1. 在某个历史版本上修改某一个位置上的值

  2. 访问某个历史版本上的某一位置的值

此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新的版本。版本编号即为当前操作的编号(从1开始编号,版本0表示初始状态数组)

(\(N\):长度,\(M\):操作数,\(1 \le N,M \le 10^6\))

显然不能开 \(M\) 棵线段树进行维护,空间会炸。

由线段树得到启发,每次修改时只会经过约 \(\mathrm{log_2} \ N\) 个节点,所以每次只需要动态开点增加一条链,改变的区间(儿子)开点,不改变的区间不变,对应到原版本位置上,记录新根节点编号即可。这样空间复杂度就是 \(O(2n-1+m \ \mathrm{log} \ n) = O(2n+m \ \mathrm{log} \ n)\),实际开个 tree[MAXN<<5] 一般也不会爆。

每次查询时只需要沿对应版本的根节点向下查找即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
struct Stree{
	int ls,rs;//左儿子 右儿子 
	int num;
	#define ls(x) tree[x].ls
	#define rs(x) tree[x].rs
	#define num(x) tree[x].num
}tree[N<<5];
int n,m,a[N],root[N<<5],cnt;
int rt,op,x,y;
int build(int l,int r){//l r 为当前节点区间
	int x=++cnt;
	if(l==r){
		num(x)=a[l];
		return x;
	}
	int mid=l+r>>1;
	ls(x)=build(l,mid);
	rs(x)=build(mid+1,r);
	return x;
}
int change(int x,int l,int r,int i,int num){//x 为原版当前节点  l r 为当前节点区间
	int y=++cnt;//y 为新版当前节点
	if(l==r){
		num(y)=num;
		return y;
	}
	int mid=l+r>>1;
	ls(y)=ls(x);
	rs(y)=rs(x);
	if(i<=mid)//更改左儿子则新建左儿子,更改右儿子则新建右儿子
		ls(y)=change(ls(x),l,mid,i,num);
	else
		rs(y)=change(rs(x),mid+1,r,i,num);
	return y;
}
int query(int x,int l,int r,int i){
	if(l==r)
		return num(x);
	int mid=l+r>>1;
	if(i<=mid)
		return query(ls(x),l,mid,i);
	else
		return query(rs(x),mid+1,r,i);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	root[0]=build(1,n);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&rt,&op,&x);
		if(op==1){
			scanf("%d",&y);
			root[i]=change(root[rt],1,n,x,y);
		}else{
			printf("%d\n",query(root[rt],1,n,x));
			root[i]=root[rt];
		}
	}
	return 0;
}

标签:持久,rs,int,线段,num,ls,版本
From: https://www.cnblogs.com/z-Sqrt-xf/p/18458825/Persistent-Segement-Tree

相关文章

  • 鸿蒙数据持久化sqlite
    1.数据查询model:entry/src/main/model/TaskModel.etsimportrelationalStorefrom'@ohos.data.relationalStore';import{common}from'@kit.AbilityKit';importTaskInfofrom'../ets/viewModel/TaskInfo';classTaskModel{priv......
  • 李超线段树
    1问题李超线段树是线段树的一种变种,主要用于维护二维平面上的直线信息以及查询操作。它的应用范围很广,只要式子的形式能转化为一次函数就可以考虑使用李超线段树进行求解/优化。具体的,李超线段树支持下面两种操作:动态在平面中插入一条线段/直线。在平面上询问与一条直线......
  • 鸿蒙首选项数据持久化
    1.ets/common/util/PreferencesUtils.etsimport{common}from'@kit.AbilityKit';import{preferences}from'@kit.ArkData';classPreferencesUtil{prefMap:Map<string,preferences.Preferences>=newMap()/*加载首选项*/lo......
  • 【Unity】数据持久化PlayerPrefs
    PlayerPrefs存储数据,数据为[key-value]形式可以用保存用户的设置、偏好;历史得分数据等;保存的数据位置不同的系统数据将被保存在不同的位置。Windows系统保存的数据将会被存储在系统注册表中,位置如下:(编辑器运行模式)\HKEY_CURRENT_USER\SOFTWARE\Unity\UnityEditor\DefaultCom......
  • 【Redis】持久化(下)-- AOF
    文章目录AOF概念如何使用AOFAOF工作流程命令写入演示文件同步策略`AOF`的重写机制概念触发重写机制`AOF`重写流程启动时数据恢复混合持久化总结AOF概念AOF持久化:以独立日志的方式记录每次的写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的.AOF的主要......
  • 【主机持久化】概述
    简单来说持久化就是开后门,目标机器重启或者漏洞修补后仍可以继续控制,比如通过钓鱼获得初始权限后,如果没做持久化Beacon丢失可能就很难再次获得,安装持久化通常需要进行一些配置更改或将后门写入磁盘,一方面持久化具有很高的检测风险,另一方面在长期渗透中非常有用(实际上是必不可少的......
  • 【主机持久化】计划任务
    Windows计划任务允许我们创建在预定触发器上执行的“任务”。该触发器可以是一天中的某个时间、用户登录时、计算机空闲时、计算机锁定时,或者上述情况的组合例如创建一个计划任务,每小时执行一次PowerShell有效负载为了避免在IEX命令中处理大量引号,可以将其编码为base64,然......
  • 【主机持久化】注册表自动运行
    HKCU和HKLM中的AutoRun值允许应用程序在开机时启动,通常这些值用于启动本机和第三方应用程序,例如软件更新程序、下载助手、驱动程序实用程序等beacon>cdC:\ProgramDatabeacon>uploadC:\Payloads\http_x64.exebeacon>mvhttp_x64.exeupdater.exebeacon>execute-asse......
  • 【主机持久化】启动文件夹
    用户每次登录时,启动文件夹中的应用程序、文件和快捷方式会自动启动,通常用来引导用户的环境配置(设置壁纸、快捷方式等),可以通过CobaltStrike客户端中执行beacon>execute-assemblyC:\Tools\SharPersist\SharPersist\bin\Release\SharPersist.exe-tstartupfolder-c"C:\Windows......
  • 【CRTO】主机持久化
    一、概述二、计划任务三、启动文件夹四、注册表自动运行五、COM劫持本章主要是通过计划任务、启动文件夹、注册表自动运行、COM劫持等方法进行持久化后门安装一、概述简单来说持久化就是开后门,目标机器重启或者漏洞修补后仍可以继续控制,比如通过钓鱼获得初始权限后,如......