函数库 线段树lazy标记
如果在题目中使某个区间所有元素的对应值*x或+-x,直接用线段树对每个元素进行计算,时间复杂度升高为nlogn,而用lazy标记可以减小时间复杂度。
假设需要对某区间+num;
void pushup(int p)
{//数值向上传递
dat[p]=dat[2*p]+dat[2*p+1];
}
void pushdown(int p,int m)
{//将lazy标记传递给左儿子和右儿子,同时初始化自己的lazy标记,这样在未来的运算中,减少所走步数。
if(add[p])
{
add[p*2]+=add[p];
add[p*2+1]+=add[p];
dat[p*2]+=(m-(m/2))*add[p];
dat[p*2+1]+=(m/2)*add[p];
add[p]=0;
}
}
void update(int x,int y,long long num,int l,int r,int p)
{//更新每个节点的数值,与change函数类似,但是多了lazy标记的运算。
if(x<=l&&r<=y)
{
add[p]+=num;
dat[p]+=num*(r-l+1);
return ;
}
pushdown(p,r-l+1);
int mid=(l+r)/2;
if(x<=mid)
update(x,y,num,l,mid,p*2);
if(y>mid)
update(x,y,num,mid+1,r,p*2+1);
pushup(p);
}
void build(int p,int l,int r)
{
add[p]=0;
if(l==r) {dat[p]=a[l];return;}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
dat[p]=dat[p*2]+dat[p*2+1];
}
long long find(int p,int l,int r,int x,int y)
{//计算区间和的时候,必须考虑到lazy标记的传递。
if((x<=l)&&(r<=y))return dat[p];
pushdown(p,r-l+1);
int mid=(l+r)/2;
if(mid>=y)return find(p*2,l,mid,x,y);
if(mid<x)return find(p*2+1,mid+1,r,x,y);
long long t=find(p*2,l,mid,x,y)+find(p*2+1,mid+1,r,x,y);
return t;
}
浙公网安备 33010602011771号