线段树
线段树1
- 区间加
- 区间求和
点击查看代码
#include<bits/stdc++.h>
#define il inline
#define ri register int
#define int long long
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int maxn=5e5+5;
int n,mm;
int tree[maxn],lz[maxn],v[maxn];
il int read()
{
int as=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();
return as*f;
}
il void pushup(int rt)
{
tree[rt]=tree[rs]+tree[ls];
}
il void pushdown(int rt,int l,int r)
{
if(lz[rt]==0) return;
int m=l+r>>1;
lz[ls]+=lz[rt],tree[ls]+=lz[rt]*(m-l+1);
lz[rs]+=lz[rt],tree[rs]+=lz[rt]*(r-m);
pushup(rt),lz[rt]=0;
}
il void build(int rt,int l,int r)
{
if(l==r){tree[rt]=v[l];return;}
int m=l+r>>1;
build(ls,l,m),build(rs,m+1,r);
pushup(rt);
}
il void update(int rt,int ql,int qr,int l,int r,int k)
{
if(ql<=l&&r<=qr)
return lz[rt]+=k,tree[rt]+=k*(r-l+1),void();
pushdown(rt,l,r);
int m=l+r>>1;
if(ql<=m) update(ls,ql,qr,l,m,k);
if(qr>m) update(rs,ql,qr,m+1,r,k);
pushup(rt);
}
il int query(int rt,int ql,int qr,int l,int r)
{
if(ql<=l&&r<=qr) return tree[rt];
int m=l+r>>1,sum=0;
pushdown(rt,l,r);
if(ql<=m) sum+=query(ls,ql,qr,l,m);
if(qr>m) sum+=query(rs,ql,qr,m+1,r);
return sum;
}
signed main()
{
n=read(),mm=read();
for(ri i=1;i<=n;i++) v[i]=read();
build(1,1,n);
for(ri i=1;i<=mm;i++)
{
int q=read();
if(q==1)
{
int ql=read(),qr=read(),k=read();
update(1,ql,qr,1,n,k);
}
else
{
int ql=read(),qr=read();
cout<<query(1,ql,qr,1,n)<<endl;
}
}
return 0;
}
线段树2
- 区间乘
- 区间加
- 区间求和
点击查看代码
#include<bits/stdc++.h>
#define il inline
#define ri register int
#define ru register unsigned int
#define mid (l+r>>1)
#define rs rt<<1|1
#define ls rt<<1
#define int long long
using namespace std;
const int maxn=1e5+1;
struct Node{int val,mul,add;}tr[maxn<<2];
int n,m,MOD;
il int rd()
{
int as=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();
return as*f;
}
il void wt(int x){if(x>9) wt(x/10);putchar(x%10+48);}
il void pushup(int rt){tr[rt].val=(tr[ls].val+tr[rs].val)%MOD,tr[rt].val%=MOD;}
il void pushdown(int rt,int l,int r)
{
tr[ls].val=(tr[ls].val*tr[rt].mul+(mid-l+1)*tr[rt].add)%MOD,
tr[rs].val=(tr[rs].val*tr[rt].mul+(r-mid)*tr[rt].add)%MOD;
tr[ls].mul=(tr[ls].mul*tr[rt].mul)%MOD,
tr[rs].mul=(tr[rs].mul*tr[rt].mul)%MOD,
tr[ls].add=(tr[ls].add*tr[rt].mul+tr[rt].add)%MOD,
tr[rs].add=(tr[rs].add*tr[rt].mul+tr[rt].add)%MOD,
tr[rt].mul=1,tr[rt].add=0;
}
il void updmul(int rt,int l,int r,int ql,int qr,int k)
{
if(ql<=l&&r<=qr)
{
tr[rt].mul=(tr[rt].mul*k)%MOD,
tr[rt].add=(tr[rt].add*k)%MOD,
tr[rt].val=(tr[rt].val*k)%MOD;return;
}
pushdown(rt,l,r);
if(ql<=mid) updmul(ls,l,mid,ql,qr,k);
if(qr>mid) updmul(rs,mid+1,r,ql,qr,k);
pushup(rt);
}
il void updadd(int rt,int l,int r,int ql,int qr,int k)
{
if(ql<=l&&r<=qr)
{
tr[rt].add+=k,tr[rt].add%=MOD,
tr[rt].val=(tr[rt].val+(r-l+1)*k)%MOD;
return;
}
pushdown(rt,l,r);
if(ql<=mid) updadd(ls,l,mid,ql,qr,k);
if(qr>mid) updadd(rs,mid+1,r,ql,qr,k);
pushup(rt);
}
il int query(int rt,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr) return tr[rt].val%MOD;
pushdown(rt,l,r);int sum=0;
if(ql<=mid) sum+=query(ls,l,mid,ql,qr)%MOD,sum%=MOD;
if(qr>mid) sum+=query(rs,mid+1,r,ql,qr)%MOD,sum%=MOD;
return sum%MOD;
}
il void build(int rt,int l,int r)
{
tr[rt].mul=1,tr[rt].add=0;
if(l==r) return tr[rt].val=rd()%MOD,void();
build(ls,l,mid),build(rs,mid+1,r),pushup(rt);
}
signed main()
{
n=rd(),m=rd(),MOD=rd();
build(1,1,n);
for(ru i=1,op,ql,qr,k;i<=m;++i)
{
op=rd();
if(op==1) ql=rd(),qr=rd(),k=rd(),updmul(1,1,n,ql,qr,k);
else if(op==2) ql=rd(),qr=rd(),k=rd(),updadd(1,1,n,ql,qr,k);
else ql=rd(),qr=rd(),wt(query(1,1,n,ql,qr)%MOD),putchar('\n');
}
}
吉老师线段树(线段树3)
- 区间加
- 区间取最值
- 区间求和
- 区间最大值
- 区间历史最大值
\(luogu\space 6242\)
一看就懂 \(blog\)
\(WC\) 课件
点击查看代码
//吉司机线段树
/*
1.mRange_add; 2.mRange_Min 3.qRange_sum
4.qRange_Max 5. qRange_Max(Include Previous Versions)
max1: 最大值 max2: 严格次大值 maxhis: 历史最大值 cnt: 最大值出现次数
lz1: 当前区间最大值的加标记
lz2: 当前区间非最大值的加标记
lz3: 当前区间最大值历史上加的最多的那次的加标记
lz4: 非最大值的历史上加的最多的那次的加标记
k1/k2: 当前/历史最大值要加的数 k3/k4: 当前/历史非最大值要加的数
*/
#include<bits/stdc++.h>
#define cs const
#define il inline
#define pc(i) putchar(i)
#define LL long long
#define fi first
#define se second
#define pub push_back
#define fo(i,j,k) for(int i=(j);(i)<=(k);++(i))
#define of(i,j,k) for(int i=(j);(i)>=(k);--(i))
#define pii pair<int,int>
using namespace std;
cs LL inf=1e18+7,N=5e5+7;
LL FL,CH;
template<typename T> bool in(T&a)
{
for(FL=1;!isdigit(CH)&&CH!=EOF;CH=getchar())
if(CH=='-')FL=-1;
for(a=0;isdigit(CH);CH=getchar())
a=a*10+CH-'0';
return a*=FL,CH==EOF?0:1;
}
template<typename T,typename...Args>
LL in(T&a,Args&...args){return in(a)+in(args...);}
void wt(LL x){if(x<0)x=-x,pc('-');if(x>9)wt(x/10);pc(x%10|48);}
int n,m; LL A[N];
namespace Seg
{
#define ls (x<<1)
#define rs (x<<1|1)
#define mid (l+r>>1)
struct seg{ LL sum,max,sec,maxh,cnt,len,lz1,lz2,lz3,lz4; }t[N<<1];
il void pushup(cs int x)
{
t[x].max=max(t[ls].max,t[rs].max);
t[x].maxh=max(t[ls].maxh,t[rs].maxh),
t[x].sum=t[ls].sum+t[rs].sum;
if(t[ls].max==t[rs].max)
t[x].sec=max(t[ls].sec,t[rs].sec),
t[x].cnt=t[ls].cnt+t[rs].cnt;
else if(t[ls].max>t[rs].max)
t[x].sec=max(t[ls].sec,t[rs].max),t[x].cnt=t[ls].cnt;
else t[x].sec=max(t[ls].max,t[rs].sec),t[x].cnt=t[rs].cnt;
}
il void update(cs int x,cs int k1,cs int k2,cs int k3,cs int k4)
{
t[x].sum+=k1*t[x].cnt+k3*(t[x].len-t[x].cnt);
t[x].maxh=max(t[x].maxh,t[x].max+k2);
t[x].lz3=max(t[x].lz3,t[x].lz1+k2);
t[x].lz4=max(t[x].lz4,t[x].lz2+k4);
t[x].max+=k1,t[x].lz1+=k1,t[x].lz2+=k3;
if(t[x].sec!=-inf) t[x].sec+=k3;
}
il void pushdown(cs int x)
{
int Max=max(t[ls].max,t[rs].max);
if(t[ls].max==Max)
update(ls,t[x].lz1,t[x].lz3,t[x].lz2,t[x].lz4);
else update(ls,t[x].lz2,t[x].lz4,t[x].lz2,t[x].lz4);
if(t[rs].max==Max)
update(rs,t[x].lz1,t[x].lz3,t[x].lz2,t[x].lz4);
else update(rs,t[x].lz2,t[x].lz4,t[x].lz2,t[x].lz4);
t[x].lz1=t[x].lz2=t[x].lz3=t[x].lz4=0;
}
void build(cs int x,cs int l,cs int r)
{
t[x].len=r-l+1;
if(l==r)
return t[x].max=t[x].maxh=t[x].sum=A[l],
t[x].cnt=1,t[x].sec=-inf,void();
build(ls,l,mid),build(rs,mid+1,r),pushup(x);
}
void update_add(cs int x,cs int l,cs int r,cs int ql,cs int qr,cs int k)
{
if(ql<=l&&r<=qr) return update(x,k,k,k,k);
pushdown(x);
if(ql<=mid) update_add(ls,l,mid,ql,qr,k);//1 <=
if(qr>mid) update_add(rs,mid+1,r,ql,qr,k);//1 >
pushup(x);
}
void update_min(cs int x,cs int l,cs int r,cs int ql,cs int qr,cs int k)
{
if(k>=t[x].max) return;//2 t[x].sec<=k<=t[x].max
if(ql<=l&&r<=qr&&k>=t[x].sec)
return update(x,k-t[x].max,k-t[x].max,0,0),void();
pushdown(x);
if(ql<=mid) update_min(ls,l,mid,ql,qr,k);
if(qr>mid) update_min(rs,mid+1,r,ql,qr,k);
pushup(x);
}
LL query_sum(cs int x,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[x].sum;
pushdown(x); LL re=0;
if(ql<=mid) re+=query_sum(ls,l,mid,ql,qr);
if(qr>mid) re+=query_sum(rs,mid+1,r,ql,qr);
return re;
}
LL query_max(cs int x,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[x].max;
pushdown(x); LL re=-inf;
if(ql<=mid) re=max(re,query_max(ls,l,mid,ql,qr));
if(qr>mid) re=max(re,query_max(rs,mid+1,r,ql,qr));
return re;
}
LL query_maxh(cs int x,cs int l,cs int r,cs int ql,cs int qr)
{
if(ql<=l&&r<=qr) return t[x].maxh;
pushdown(x); LL re=-inf;
if(ql<=mid) re=max(re,query_maxh(ls,l,mid,ql,qr));
if(qr>mid) re=max(re,query_maxh(rs,mid+1,r,ql,qr));
return re;
}
#undef ls
#undef rs
#undef mid
}
signed main()
{
in(n,m); fo(i,1,n) in(A[i]);
Seg::build(1,1,n);
while(m--)
{
int op,l,r,k; in(op,l,r);
if(op==1) in(k),Seg::update_add(1,1,n,l,r,k);
else if(op==2) in(k),Seg::update_min(1,1,n,l,r,k);
else if(op==3) wt(Seg::query_sum(1,1,n,l,r)),pc('\n');
else if(op==4) wt(Seg::query_max(1,1,n,l,r)),pc('\n');
else wt(Seg::query_maxh(1,1,n,l,r)),pc('\n');
}
return 0;
}

浙公网安备 33010602011771号