秋实大哥是一个儒雅之人,昼听笙歌夜醉眠,若非月下即花前。
所以秋实大哥精心照料了很多花朵。现在所有的花朵排成了一行,每朵花有一个愉悦值。
秋实大哥每天要对着某一段连续的花朵歌唱,然后这些花朵的愉悦值都会增加一个相同的值 v ( v 可能为负)。
同时他想知道每次他唱完歌后这一段连续的花朵的愉悦值总和是多少。
Input
第一行有一个整数 n ,表示花朵的总数目。
第二行包含 n 个整数 ai ,表示第 i 朵花初始的愉悦值。
第三行包含一个整数 m ,表示秋实大哥唱了 m 天的歌。
接下来 m 行,每行包含三个整数 l r v ,表示秋实大哥对着 [l,r] 这个区间内的花朵歌唱,每朵花的愉悦值增加了 v 。
1≤n,m,ai,|v|≤100000 , 1≤l≤r≤n。
Output
输出共 m 行,第 i 行表示秋实大哥完成第 i 天的歌唱后,那一段花朵的愉悦值总和。
Sample input and output
Sample Input | Sample Output |
---|---|
3 0 0 0 3 1 2 1 1 2 -1 1 3 1 | 2 0 3 |
#include <iostream>
#include <cstdio>
#define lid (id << 1)
#define rid (id << 1 | 1)
using namespace std;
const int N=100005;
struct node
{
int l,r;
long long hp,lazy;
void fun(long long val)
{
lazy += val;
hp += val * (r - l + 1);
}
}tr[N * 4];
int a[N];
void push_up(int id)
{
tr[id].hp = tr[lid].hp + tr[rid].hp;
}
void push_down(int id)
{
if(tr[id].lazy)
{
tr[lid].fun(tr[id].lazy);
tr[rid].fun(tr[id].lazy);
tr[id].lazy = 0;
}
}
void build(int id, int l,int r)
{
tr[id].l = l; tr[id].r = r;
if(l == r)
{
tr[id].hp = a[l];
return;
}
int mid = (l + r) >> 1;
build(lid, l, mid);
build(rid, mid + 1, r);
push_up(id);
}
long long query(int id, int l, int r)
{
if(tr[id].l == l && tr[id].r == r)
{
return tr[id].hp;
}
push_down(id);
int mid = (tr[id].l + tr[id].r) >> 1;
if(r <= mid) return query(lid, l, r);
if(l > mid) return query(rid, l, r);
return query(lid, l, mid)+query(rid, mid + 1,r);
}
void update(int id,int l,int r,int v)
{
if(tr[id].l == l && tr[id].r == r)
{
tr[id].fun(v);
return;
}
push_down(id);
int mid = (tr[id].l + tr[id].r) >> 1;
if(r <= mid)
update(lid, l, r, v);
else if(l > mid)
update(rid, l, r, v);
else
{
update(lid, l, mid, v);
update(rid, mid+1, r, v);
}
push_up(id);
}
int main()
{
int n,m;
int l,r,v;
scanf("%d",&n);
for(int i = 1;i <= n; i ++)
scanf("%d",&a[i]);
build(1,1,n);
scanf("%d",&m);
while(m --)
{
scanf("%d%d%d",&l,&r,&v);
update(1,l,r,v);
printf("%lld\n",query(1,l,r));
}
return 0;
}
用线段树实现。涉及更新区间,询问区间。
节点记录区间段、区间总愉悦值、lazy值。根据初始值建树。更新操作更新区间,并在更新时进行懒操作标记。
询问时询问区间,通过lazy值向下递归,向上返回,得到结果。