区间查改(线段树)
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));
}
}
}
谢谢
以上是关于区间查改(线段树)的主要内容,如果未能解决你的问题,请参考以下文章