线段树

线段树1

  • 区间加
  • 区间求和

\(luogu\space 3372\)

点击查看代码
#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

  • 区间乘
  • 区间加
  • 区间求和

\(luogu \space 3373\)

点击查看代码
#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;
}
posted @ 2022-09-23 15:03  Bertidurlah  阅读(28)  评论(0)    收藏  举报