线段树区间修改和区间求和
const int N=100010;
struct SegTree
{
int l,r;
long long sum;
long long add;
}tr[N<<2];
int w[N];
int n,m;
void update(int u)
{
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;//确定的法则
}
void pushdown(int u)//维护
{
SegTree &root=tr[u],&left=tr[u<<1],&right=tr[u<<1|1];//引用
if(root.add)
{
left.add+=root.add;
left.sum+=(long long)(left.r-left.l+1)*root.add;
right.add+=root.add;
right.sum+=(long long)(right.r-right.l+1)*root.add;
root.add=0;//标记归零
}
}
void build(int u,int l,int r)
{
if(l==r) tr[u]={l,r,w[r],0};//初始化
else {
tr[u]={l,r};
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
update(u);
}
}
void change(int u,int l,int r,int k)
{
if(tr[u].l>=l&&tr[u].r<=r)//完全在区间内
{
tr[u].add+=k;
tr[u].sum+=(long long)(tr[u].r-tr[u].l+1)*k;
}
else{
pushdown(u);
int mid=(tr[u].l+tr[u].r)>>1;
if(l<=mid) change(u<<1,l,r,k);
if(r>mid) change(u<<1|1,l,r,k);
update(u);
}
}
long long ask(int u,int l,int r)
{
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].sum;
else{
pushdown(u);
int mid=(tr[u].l+tr[u].r)>>1;
long long res=0;
if(l<=mid) res=ask(u<<1,l,r);
if(r>mid) res+=ask(u<<1|1,l,r);
return res;
}
}
总结:
线段树区间最大值
const int N=200005;
int num[N<<2];
int s[N<<2];
void update(int u)
{
s[u]=max(s[u<<1],s[u<<1|1]);
}
void build(int u,int l,int r)
{
if(l==r)
{
s[u]=num[l];
return;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
update(u);
}
void change(int u,int l,int r,int index,int k)
{
if(l==r)
{
s[u]=k;
return;
}
int mid=(l+r)>>1;
if(index<=mid) change(u<<1,l,mid,index,k);
else change(u<<1|1,mid+1,r,index,k);
update(u);
}
int ask(int u,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return s[u];
int mid=(l+r)>>1;
int ans=-1000;
if(L<=mid) ans=max(ans,ask(u<<1,l,mid,L,R));
if(R>mid) ans=max(ans,ask(u<<1|1,mid+1,r,L,R));
return ans;
}
总结:
线段树区间乘法和区间求和
typedef long long ll;
const int N=100010;
int n,m,mod;
struct SegTree{
int l,r;
ll sum;
ll add;
ll mul;
}tr[N<<2];
int w[N];
void update(int u)
{
tr[u].sum=(tr[u<<1].sum+tr[u<<1|1].sum)%mod;
return;
}
void pushdown(int u)
{
SegTree &root=tr[u], &left=tr[u<<1], &right=tr[u<<1|1];
left.sum=(left.sum*root.mul+root.add*(left.r-left.l+1))%mod;
right.sum=(right.sum*root.mul+root.add*(right.r-right.l+1))%mod;
left.mul=(left.mul*root.mul)%mod;
right.mul=(right.mul*root.mul)%mod;
left.add=(left.add*root.mul+root.add)%mod;
right.add=(right.add*root.mul+root.add)%mod;
root.add=0;
root.mul=1;
return;
}
void build(int u,int l,int r)
{
tr[u].l=l;
tr[u].r=r;
tr[u].mul=1;
if(l==r) {
tr[u].sum=w[l]%mod;
return;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
update(u);
return;
}
void changeMul(int u,int l,int r,int k)
{
if(tr[u].l>=l&&tr[u].r<=r)
{
tr[u].add=(tr[u].add*k)%mod;
tr[u].mul=(tr[u].mul*k)%mod;
tr[u].sum=(tr[u].sum*k)%mod;
return;
}
pushdown(u);
int mid=(tr[u].l+tr[u].r)>>1;
if(l<=mid) changeMul(u<<1,l,r,k);
if(r>mid) changeMul(u<<1|1,l,r,k);
update(u);
return;
}
void changeAdd(int u,int l,int r,int k)
{
if(tr[u].l>=l&&tr[u].r<=r)
{
tr[u].add=(tr[u].add+k)%mod;
tr[u].sum=(tr[u].sum+k*(tr[u].r-tr[u].l+1))%mod;
return;
}
pushdown(u);
int mid=(tr[u].l+tr[u].r)>>1;
if(l<=mid) changeAdd(u<<1,l,r,k);
if(r>mid) changeAdd(u<<1|1,l,r,k);
update(u);
}
ll ask(int u,int l, int r)
{
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].sum;
else {
pushdown(u);
ll res=0;
int mid=(tr[u].r+tr[u].l)>>1;
if(l<=mid) res=(res+ask(u<<1,l,r))%mod;
if(r>mid) res=(res+ask(u<<1|1,l,r))%mod;
return res;
}
}