线段树基础

关键:

  1. 数组空间4:二叉树节点数为2n-1,所有根节点下有两个空节点,所以节点数为4*n-1;
  2. lazy数组:因为修改范围已经包括整个区间,所以不再需要下放
  3. 函数模块:(build建树,down下放)+区间操作
  4. 注意:操作前下放,操作后赋值

代码:区间加法,区间求和

#include<bits/stdc++.h>
using namespace std;
int n,m;
long long tree[400000],lazy[400000],ans;
void down(int num,int l,int r)
{
	int mid=(l+r)>>1;
	lazy[num*2]+=lazy[num];
	tree[num*2]+=(mid-l+1)*lazy[num];
	lazy[num*2+1]+=lazy[num];
	tree[num*2+1]+=(r-mid)*lazy[num];
}
void build(int num,int l,int r)
{
	if(l == r)
	{
		cin>>tree[num];
		return;
	}
	int mid=(l+r)>>1;
	build(num*2,l,mid);
	build(num*2+1,mid+1,r);
	tree[num]=tree[num*2]+tree[num*2+1];
}
void jia(int num,int l,int r,int ml,int mr,int k)
{
	if(l >= ml && r <= mr)
	{
		lazy[num]+=k;
		tree[num]+=(r-l+1)*k;
		return;
	}
	int mid=(l+r)>>1;
	down(num,l,r);
	lazy[num]=0;
	if(mid >= ml)
		jia(num*2,l,mid,ml,mr,k);
	if(mid < mr)
		jia(num*2+1,mid+1,r,ml,mr,k);
	tree[num]=tree[num]+(min(mr,r)-max(l,ml)+1)*k;
}
void getsum(int num,int l,int r,int ml,int mr)
{
	if(l >= ml && r <= mr)
	{
		ans+=tree[num];
		return;
	}
	int mid=(l+r)>>1;
	down(num,l,r);
	lazy[num]=0;
	if(mid >= ml)
		getsum(num*2,l,mid,ml,mr);
	if(mid < mr)
		getsum(num*2+1,mid+1,r,ml,mr);
}
int main()
{
	cin>>n>>m;
	build(1,1,n);
	for(int i=1; i<=m; i++)
	{
		int x,y,z,k;
		cin>>z>>x>>y;
		if(z == 1)
		{
			cin>>k;
			jia(1,1,n,x,y,k);
		}
		else
		{
			getsum(1,1,n,x,y);
			cout<<ans<<endl;
			ans=0;
		}
	}
	return 0;
}

代码:区间加法、乘法,区间求和

#include<bits/stdc++.h>
using namespace std;
long long n,m,p;
long long tree[800000],lazy[800000],lazyz[800000],ans;
int getsum(int num,int l,int r,int ml,int mr);

关键代码

void down(int num,int l,int r)
{
	int mid=(r+l)>>1;
	tree[num*2]=(tree[num*2]*lazyz[num]+lazy[num]*(mid-l+1))%p;
	tree[num*2+1]=(tree[num*2+1]*lazyz[num]+lazy[num]*(r-mid))%p;
	
	lazyz[num*2]=(lazyz[num]*lazyz[num*2])%p;
	lazyz[num*2+1]=(lazyz[num]*lazyz[num*2+1])%p;
	lazy[num*2]=(lazy[num*2]*lazyz[num]+lazy[num])%p;
	lazy[num*2+1]=(lazy[num*2+1]*lazyz[num]+lazy[num])%p;
	
	lazy[num]=0;
	lazyz[num]=1;
}
int getsum(int num,int l,int r,int ml,int mr)
{
    int sum=0;
    if(l >= ml && r <= mr)
    {
        return (tree[num]%p);
    }
    int mid=(l+r)>>1;
    down(num,l,r);
    if(mid >= ml)
        sum+=getsum(num*2,l,mid,ml,mr);
    if(mid < mr)
        sum+=getsum(num*2+1,mid+1,r,ml,mr);
    return sum%p;
}
void build(int num,int l,int r)
{
    if(l == r)
    {
        cin>>tree[num];
        lazyz[num]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(num*2,l,mid);
    build(num*2+1,mid+1,r);
    tree[num]=(tree[num*2]+tree[num*2+1])%p;
    lazyz[num]=1;
}
void jia(int num,int l,int r,int ml,int mr,int k)
{
    if(l >= ml && r <= mr)
    {
        lazy[num]+=k;
        tree[num]+=(r-l+1)*k;
        return;
    }
    int mid=(l+r)>>1;
    down(num,l,r);
    if(mid >= ml)
        jia(num*2,l,mid,ml,mr,k);
    if(mid < mr)
        jia(num*2+1,mid+1,r,ml,mr,k);
    tree[num]=(tree[num]+(min(mr,r)-max(l,ml)+1)*k)%p;
}
void cheng(int num,int l,int r,int ml,int mr,int k)
{
    if(l >= ml && r <= mr)
    {
    	tree[num]=(tree[num]*k)%p;
    	lazy[num]=(lazy[num]*k)%p;
        lazyz[num]=(lazyz[num]*k)%p;
        return;
    }
    int mid=(l+r)>>1;
    down(num,l,r);
    if(mid >= ml)
        cheng(num*2,l,mid,ml,mr,k);
    if(mid < mr)
        cheng(num*2+1,mid+1,r,ml,mr,k);
    tree[num]=(tree[2*num]+tree[2*num+1])%p;
}
int main()
{
    cin>>n>>m>>p;
    build(1,1,n);
    for(int i=1; i<=m; i++)
    {
        int x,y,z,k;
        cin>>z>>x>>y;
        if(z == 1)
        {
            cin>>k;
            cheng(1,1,n,x,y,k);
        }
        else if(z == 2)
        {
            cin>>k;
            jia(1,1,n,x,y,k);
        }
        else 
        {
            ans=getsum(1,1,n,x,y);
            cout<<ans<<endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值