宏定义
- #define pl a[p].tl:节点 p 的左儿子。
- #define pr a[p].tr:节点 p 的右儿子。
常量与变量
- int tot:节点个数。
- int root[i]:第 i 个历史版本的根。
- Edge a[i]:节点 i 的信息。
- int a[i].l:节点 i 维护的区间的左端点。
- int a[i].r:节点 i 维护的区间的右端点。
- int a[i].tl:节点 i 的左儿子。
- int a[i].tr:节点 i 的右儿子。
- int a[i].val:节点 i 的值。
函数
- Persistable_Segment_Tree():初始化节点个数。
- void build(int p,int l,int r):在外调用时,表示以节点 p 为根,建议一颗区间范围为 l∼r 的线段树,要求 l,r 不为 0。
- int change(int fp,int x,int v):将位置为 x 的数改为 v,fp 为上一个历史版本中维护该区间的点的编号,返回新版本中维护该区间的点的编号。
- int ask(int p,int x):询问 p 可以访问的节点中位置 x 上的数值。
代码
#define pl a[p].tl
#define pr a[p].tr
struct Persistable_Segment_Tree{
int tot,root[N*20];
struct Edge{
int l,r,tl,tr;
int val;
}a[N*20];
Persistable_Segment_Tree(){
tot=0;
}
void build(int p,int l,int r){
if(l){
a[p=++tot].l=l;
a[p].r=r;
}
if(a[p].l==a[p].r){
a[p].val=0;
return;
}
int mid=(a[p].l+a[p].r)>>1;
pl=++tot;a[pl].l=a[p].l;a[pl].r=mid;
pr=++tot;a[pr].l=mid+1;a[pr].r=a[p].r;
build(pl,0,0);build(pr,0,0);
}
int change(int fp,int x,int v){
int p=++tot;
a[p]=a[fp];
if(a[p].l==a[p].r){
a[p].val=v;
return p;
}
int mid=(a[p].l+a[p].r)>>1;
if(x<=mid)
pl=change(a[fp].tl,x,v);
else
pr=change(a[fp].tr,x,v);
return p;
}
int ask(int p,int x){
if(a[p].l==a[p].r)
return a[p].val;
int mid=(a[p].l+a[p].r)>>1;
if(x<=mid)
return ask(pl,x);
else
return ask(pr,x);
}
}tree;