主席树(萌新,复习用)
主席树是解决查询历史线段树值的问题的数据结构。
由于改变一个点值时,线段树改变不完全,所以利用一个线段树的空间存储一个历史值是很浪费空间的。
那么此时我们只需要建立一个根节点,对未改变的节点连边,对改变的节点新建节点,连边即可。
本算法思路极其简单,主要看代码实现。
void build(int &x,int l,int r)
{
if(!x)x=++cnt;
if(l==r)
{
f[x].data=a[l];
return;
}
int mid=(l+r)>>1;
build(f[x].ls,l,mid);
build(f[x].rs,mid+1,r);
}
void update(int &x,int y,int l,int r)
{
if(!x)x=++cnt;
if(l==r)
{
f[x].data=k;
return;
}
f[x]=f[y];
int mid=(l+r)>>1;
if(mid>=nl)update(f[x].ls=0,f[y].ls,l,mid);
else update(f[x].rs=0,f[y].rs,mid+1,r);
}
应用:解决区间第
每加入一个数,建立一个版本的线段树,最后利用前缀和求解第
void update(int &x,int y,int l,int r)
{
if(!x)x=++cnt;
if(l==r)
{
f[x].data=f[y].data+1;
return;
}
int mid=(l+r)>>1;
f[x]=f[y];
if(mid>=k)update(f[x].ls=0,f[y].ls,l,mid);
else update(f[x].rs=0,f[y].rs,mid+1,r);
pushup(x);
}
int search(int x,int y,int l,int r)
{
if(l==r)return t[l];
int sum=f[f[y].ls].data-f[f[x].ls].data;
int mid=(l+r)>>1;
if(k<=sum)return search(f[x].ls,f[y].ls,l,mid);
k-=sum;
return search(f[x].rs,f[y].rs,mid+1,r);
}
思路仍然非常简单,此数据结构注重于应用,所以还要多练习。
P3919 【模板】可持久化线段树 1(可持久化数组)(纯模板)
P3834 【模板】可持久化线段树 2(应用模板)
P3567 [POI2014]KUR-Couriers(简单应用)
P2468 [SDOI2010]粟粟的书架(主席树练习题,合二为一?)
P3302 [SDOI2013] 森林(树上主席树)
P4559 [JSOI2018]列队(大变式)
P2633 Count on a tree(树剖主席树)
P3293 [SCOI2016]美味(主席树变式)
P4618 [SDOI2018]原题识别(主席树树剖)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!