线段树区间/杂谈

来源:互联网 发布:仿手机淘宝 源码 编辑:程序博客网 时间:2024/05/20 23:02

接着昨天~晚上心情不错呢~尤其是刚刚小ly又见到了ly呢~希望今天晚上做题效率高一些~
线段树区间求和
struct xds{
#define lson (o<<1)
#define rson (o<<1|1)
long long sumv[MAXN<<2],lzt[MAXN<<2];
inline void pushdown(int o, int l, int r){
if(!lzt[o])return;
int mid = (l+r)>>1;
lzt[lson]+=lzt[o];lzt[rson]+=lzt[o];
sumv[lson]+=lzt[o]*(mid-l+1);sumv[rson]+=lzt[o]*(r-mid);
lzt[o]=0;
}
inline void pushup(int o){sumv[o]=sumv[lson]+sumv[rson];} //储存线段和 //可以查最小值,求和等操作
inline void build(int o,int l,int r){
lzt[o]=0;
if(l==r){sumv[o]=a[l];return;} //a为维护数组 o树中位置 ,l==r递归到最后一层;
int mid=(l+r)>>1;
build(lson,l,mid);build(rson,mid+1,r); //建左右子树
pushup(o);
}
inline long long query(int o,int l,int r,int ql,int qr){ //o l r当前节点编号区间 ql qr询问区间
if(ql<=l&&r<=qr)return sumv[o]; //包含直接计入答案
int mid=(l+r)>>1;
long long ans=0;
pushdown(o, l, r);
if(ql<=mid) ans+=query(lson,l,mid,ql,qr); //去查找左右子树
if(qr>mid) ans+=query(rson,mid+1,r,ql,qr);
return ans;
}
/* inline void change(int o,int l,int r,int q,long long v){//单点修改操作
if(l==r){
sumv[o]+=v;
return;
}
int mid=(l+r)>>1;
if(q<=mid)change(lson,l,mid,q,v);
else change(rson,mid+1,r,q,v);
pushup(o);
} */
//以下为区间
inline void adds(int o,int l,int r,int ql,int qr,long long v){
if(ql<=l&&qr>=r){sumv[o]+=v*(r-l+1);lzt[o]+=v;return;}
int mid=(l+r)>>1;
pushdown(o, l, r);
if(ql<=mid)adds(lson,l,mid,ql,qr,v);
if(qr>mid)adds(rson,mid+1,r,ql,qr,v);
pushup(o);
}
};

原创粉丝点击