动态开点就是为了应付不同的版本的线段树,目前我只会具有单点修改的动态开店线段数,核心就是为每个版本分配一个root.一个版本是依据之前某一个版本修改过来的,而你只是单点修改的话,只会增加log(n)个节点,所以把父亲版本的数据先复制过来,然后再依据是否要修改左儿子和右儿子继续递归下去,在递归时返回新的段的标号,来更新父亲的左儿子右儿子数据,这样的话空间复杂度和时间夫再度都是O(nlog(n))
struct node{
int sum,l,r;
}tr[N*30];
int rt[N];
int cnt=0;
void pushup(int p){
tr[p].sum=tr[tr[p].l].sum+tr[tr[p].r].sum;
}
int build(int s,int t){
int p=++cnt;
if(s==t){
return p;
}
int mid=(s+t)>>1;
tr[p].l=build(s,mid);
tr[p].r=build(mid+1,t);
tr[p].sum=0;
pushup(p);
return p;
}
int update(int p,int s,int t,int l,int r,int x){
int id=++cnt;
tr[id]=tr[p];
if(l<=s&&t<=r){
tr[id].sum=x;
return id;
}
int mid=(s+t)>>1;
if(l<=mid){
tr[id].l=update(tr[id].l,s,mid,l,r,x);
}
if(mid+1<=r){
tr[id].r=update(tr[id].r,mid+1,t,l,r,x);
}
pushup(id);
return id;
}
int query(int p,int s,int t,int l,int r){
if(l<=s&&t<=r){
return tr[p].sum;
}
int ans=0;
int mid=(s+t)>>1;
if(l<=mid){
ans+=query(tr[p].l,s,mid,l,r);
}
if(mid+1<=r){
ans+=query(tr[p].r,mid+1,t,l,r);
}
return ans;
}



京公网安备 11010502036488号