线段树小技巧

mft36 / 2024-11-11 / 原文

·线段树维护最大子段和

1.需要维护四个信息

开结构体一般更方便一些
struct seg{
    int sum;//区间总和 
    int mxs;//最大子段和 
    int ls;//左起最大字段和 
    int rs;//右起最大字段和 
}tr[N<<1];

2.pushup改为返回一个结构体,便于后面查询

pushup
seg pushup(seg l,seg r){
	seg k; 
	k.sum=l.sum+r.sum;
	k.mxs=max(max(l.mxs,r.mxs),l.rs+r.ls);
	k.ls=max(l.ls,l.sum+r.ls);
	k.rs=max(r.rs,r.sum+l.rs);
	return k;
}
其他函数(建树、修改)
tr[u]=pushup(tr[lc],tr[rc]);

3.查询时也返回一个结构体

四种情况分类讨论
seg qry(int u,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr) return tr[u]; 
	if(qr<=mid) return qry(lc,l,mid,ql,qr);//全部在左区间
	if(ql>mid) return qry(rc,mid+1,r,ql,qr);//全部在右区间
	return pushup(qry(lc,l,mid,ql,qr),qry(rc,mid+1,r,ql,qr));//合并左右答案
}

··线段树维护最值

查询某区间在全集中的补集的信息

这里以最小值为例
if(r<ql||l>qr)return mn[u];
if(ql<=l&&r<=qr)return 1e16;

···对于每个点维护区间和

待补