区间查改(线段树)

Posted SSL_LKJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区间查改(线段树)相关的知识,希望对你有一定的参考价值。

区间查改

在这里插入图片描述

在这里插入图片描述

输入样例

5 10
2 6 6 1 1
2 1 4
1 2 5 10
2 1 3
2 2 3
1 2 2 8
1 2 3 7
1 4 4 10
2 1 2
1 4 5 6
2 3 4

输出样例

15
34
32
33
50

解题思路

线段树区间修改+区间查询模板题

AC代码

#include<cstdio>
using namespace std;
int n,q,a[10000005],add[10000005];
long long sum[10000005];
void build(int k,int l,int r)
{
	if(l==r)
	{
		sum[k]=a[l];
		return;
	}
	int mid=(l+r)/2;
	build(k*2,l,mid);
	build(k*2+1,mid+1,r);
	sum[k]=sum[k*2]+sum[k*2+1];
}
void Add(int k,int l,int r,int v)//处理
{
	add[k]+=v;
	sum[k]+=1ll*v*1ll*(r-l+1);
}
void pushdown(int k,int l,int r,int mid)//区间
{
	if(!add[k])return;
	Add(k*2,l,mid,add[k]);
	Add(k*2+1,mid+1,r,add[k]);
	add[k]=0;
}
long long query(int k,int l,int r,int x,int y)//查询
{
	if(x<=l&&r<=y)return sum[k];
	int mid=(l+r)/2;
	long long ans=0;
	pushdown(k,l,r,mid);
	if(x<=mid)ans+=query(k*2,l,mid,x,y);
	if(y>mid)ans+=query(k*2+1,mid+1,r,x,y);
	return ans;
} 
void change(int k,int l,int r,int x,int y,int v)//修改
{
	if(x<=l&&r<=y)
	{
		Add(k,l,r,v);
		return;
	}
	int mid=(l+r)/2;
	pushdown(k,l,r,mid);
	if(x<=mid)change(k*2,l,mid,x,y,v);
	if(y>mid)change(k*2+1,mid+1,r,x,y,v);
	sum[k]=1ll*sum[k*2]+1ll*sum[k*2+1];
}
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	build(1,1,n);
	while(q--)
	{
		int k,l,r,x;
		scanf("%d",&k);
		if(k==1)
		{
			scanf("%d%d%d",&l,&r,&x);
			change(1,1,n,l,r,x);
		}
		else
		{
			scanf("%d%d",&l,&r);
			printf("%lld\\n",query(1,1,n,l,r));
		}
	}
}

谢谢

以上是关于区间查改(线段树)的主要内容,如果未能解决你的问题,请参考以下文章

求区间和(线段树)

CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)

线段树详解

线段树维护区间最大子段和

线段树

AcWing 1264. 动态求连续区间和(线段树区间查询模板)