可持久化线段树
可持久化线段树
可持久化数据结构总是可以保留每一个历史版本,并且支持操作的不可变特性
部分可持久化 所有版本都可以访问,但是只有最新版本可以修改
完全可持久化 所有版本都既可以访问又可以修改,支持将两个历史版本合并
主席树&可持久化线段树
主席树全称:可持久化权值线段树
函数式线段树:是指使用函数式编程思想的线段树,函数式线段树是[完全可持久化]的
先上动态开点:
//动态开点线段树模板 就是不用x*2与x*2+1记录左右儿子,直接用cnt记录编号以及对应l、r,减少4倍空间的超大消耗
#include<bits/stdc++.h>
#define ls a[o].l
#define rs a[o].r
using namespace std;
const int N=15000010;
int read() {
int x=0,f=1;
char ch=getchar();
while(ch<48||ch>57) {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>=48&&ch<=57) {
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}
struct Dyk {
int l,r;
} a[N];
int sum[N],tag[N],cnt=0,root;
void push_up(int o) {
sum[o]=sum[ls]+sum[rs];
}
void push_down(int o,int l,int r) {
if(tag[o]!=-1) {
int mid=(l+r)>>1;
if(!ls) ls=++cnt;
if(!rs) rs=++cnt;
sum[ls]=tag[o]*(mid-l+1);
sum[rs]=tag[o]*(r-mid);
tag[ls]=tag[o];
tag[rs]=tag[o];
tag[o]=-1;
}
}
void update(int &o,int l,int r,int x,int y,int k) {
if(o==0) o=++cnt;
if(x<=l&&r<=y) {
sum[o]=(r-l+1)*k;
tag[o]=k;
return ;
}
push_down(o,l,r);
int mid=(l+r)>>1;
if(x<=mid) update(ls,l,mid,x,y,k);
if(y>mid) update(rs,mid+1,r,x,y,k);
push_up(o);
}
int query(int o,int l,int r,int x,int y) {
int ans=0;
if(o==0) return 0;
if(l==x&&r==y) return sum[o];
int mid=(l+r)>>1;
if(y<=mid) ans+=query(ls,l,mid,x,y);
if(x>mid) ans+=query(rs,mid+1,r,x,y);
return ans;
}
int n,q;
int main() {
n=read();
q=read();
memset(tag,-1,sizeof(tag));
update(root,1,n,1,n,0);
for(int i=1; i<=q; i++) {
int x=read(),y=read(),k=read();
update(root,1,n,x,y,2-k);
printf("%d\n",n-sum[1]);
}
return 0;
}
//线段树1
#include <bits/stdc++.h>
#define ls a[o].l
#define rs a[o].r
using namespace std;
typedef long long ll;
const ll N=1500010;
ll read() {
ll x=0,f=1;
char ch=getchar();
while(ch<48||ch>57) {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>=48&&ch<=57) {
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}
struct dky {
ll l,r;
dky() {
l=r=0;
}
}a[N];
ll n,m;
ll t[N];
ll sum[N],cnt=0,tag[N],root;
void pushup(ll o) {
sum[o]=sum[ls]+sum[rs];
}
void pushtag(ll &o,ll l,ll r,ll k) {
sum[o]+=k*(r-l+1);
tag[o]+=k;
}
void pushdown(ll o,ll l,ll r) {
if(tag[o]!=0) {
int k = 0;
if(!a[o].l) a[o].l=++cnt;
if(!a[o].r) a[o].r=++cnt;
ll mid=(l+r)>>1;
pushtag(ls,l,mid,tag[o]);
pushtag(rs,mid+1,r,tag[o]);
tag[o]=0;
}
}
void update(ll &o,ll l,ll r,ll x,ll y,ll k) {
if(!o) o=++cnt;
if(x<=l&&r<=y) {
sum[o]+=(r-l+1)*k;
tag[o]+=k;
return ;
}
pushdown(o,l,r);
ll mid=(l+r)>>1;
if(x<=mid) update(ls,l,mid,x,y,k);
if(y>mid) update(rs,mid+1,r,x,y,k);
pushup(o);
}
ll query(ll o,ll l,ll r,ll x,ll y) {
ll ans=0;
if(!o) return 0;
if(l>=x&&r<=y) return sum[o];
pushdown(o,l,r);
ll mid=(l+r)>>1;
if(x<=mid) ans+=query(ls,l,mid,x,y);
if(y>mid) ans+=query(rs,mid+1,r,x,y);
return ans;
}
int main() {
n=read();
m=read();
for(ll i=1; i<=n; i++) {
t[i]=read();
update(root,1,n,i,i,t[i]);
}
for(ll i=1; i<=m; i++) {
ll op=read();
if(op==1) {
ll x=read(),y=read(),k=read();
update(root,1,n,x,y,k);
}
if(op==2) {
ll x=read(),y=read();
printf("%lld\n",query(root,1,n,x,y));
}
}
return 0;
}
······
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?