codevs 1082
线段树:区间更新,区间求和
重点在于lazy的使用
与单点查询不同的是在更新和查询时都需要pushdown(下放lazy)
#include <iostream>
#include <cstdio>
#include <cstring>
#define lson u << 1,l,mid
#define rson u << 1 | 1,mid + 1,r
#define ll long long
using namespace std;
const int maxn = 200000 + 5;
int n,q,tt,a,b,c;
struct node
{
ll sum,lazy;
}t[maxn << 2];
void pushup(int u){ t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;}
void pushdown(int u,int m)//下放lazy
{
if(t[u].lazy)
{
t[u << 1].lazy += t[u].lazy;
t[u << 1 | 1].lazy += t[u].lazy;
t[u << 1].sum += (m - (m >> 1)) * t[u].lazy;
t[u << 1 | 1].sum += (m >> 1) * t[u].lazy;
t[u].lazy = 0;
}
}
void build(int u,int l,int r)
{
t[u].lazy = 0;
if(l == r)
{
scanf("%lld",&t[u].sum);
return;
}
int mid = (l + r) >> 1;
build(lson); build(rson);
pushup(u);
}
void update(int u,int l,int r,int a,int b,int c)
{
if(a <= l && r <= b)
{
t[u].lazy += c;//更新lazy标记
t[u].sum += (r - l + 1) * c;
return;
}
int mid = (l + r) >> 1;
pushdown(u,r - l + 1);//下放lazy
if(a <= mid) update(lson,a,b,c);
if(mid < b) update(rson,a,b,c);
pushup(u);
}
ll query(int u,int l,int r,int a,int b)
{
if(a <= l && r <= b) return t[u].sum;
int mid = (l + r) >> 1;
pushdown(u,r - l + 1);//下放lazy
ll ans = 0;
if(a <= mid) ans += query(lson,a,b);
if(mid < b) ans += query(rson,a,b);
return ans;
}
int main()
{
scanf("%d",&n);
build(1,1,n);
scanf("%d",&q);
for(int i = 1; i <= q; ++i)
{
scanf("%d",&tt);
if(tt == 1)
{
scanf("%d%d%d",&a,&b,&c);
update(1,1,n,a,b,c);
}
else
{
scanf("%d%d",&a,&b);
printf("%lld\n",query(1,1,n,a,b));
}
}
return 0;
}