为了解决这个问题 著名的Lazy-Tag思想应运而生
每次都把所有区间修改了太慢了 不如懒一点 先把帐记着 到时候再做
懒-记帐=Lazy-Tag
怎么记录呢? 我们需要再加一个 lazy 标
记
用来记录当前节点为根的子树 是否需要统一加一个数 具体要加多少
我们的程序就要改一下了
+每当碰到要当前区间完全被欲修改区间覆盖时 直接给加在标记上 然后退出
+每次访问到一个节点时 首先清空当前节点的标记
-访问包括各种操作 不管是插入 删除 还是查询 甚至是仅仅用到节点的s[]值
-清空不仅仅是用标记更新当前节点 还包括把标记下传给左右子树
*我们用一个单独的过程clean来执行清空标记的操作
需要注意的是 叶子节点不用下传标记 否则RE
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
4 55 9
#include <stdio.h>
#include <algorithm>
using namespace std;
#define maxn 200010
typedef long long ll;
#define ls o<<1
#define rs o<<1|1
ll a[maxn];
struct node{
ll l,r,x;
ll lazy;
}t[maxn<<2];
inline void push_up(int o)
{
t[o].x=t[ls].x+t[rs].x;//向上更新
}
inline void pushdown(int o,int l,int r)
{
if(t[o].lazy)// 把标记下传给左右子树
{
t[ls].lazy+=t[o].lazy;
t[rs].lazy+=t[o].lazy;
t[ls].x+=t[o].lazy*l;
t[rs].x+=t[o].lazy*r;
t[o].lazy=0;//每次访问到一个节点时 首先清空当前节点的标记
}
}
void build(int l,int r,int o)
{
t[o].l=l,t[o].r=r;
if(l==r)
{
t[o].x=a[l];return ;
}
int mid=(l+r)>>1;
build(l,mid,ls),build(mid+1,r,rs);
push_up(o);
}
inline void updata( int l,int r,int c,int o)
{
if(t[o].l>=l&&t[o].r<=r)//每次访问到一个节点时 首先清空当前节点的标记
{
t[o].x+=c*(t[o].r-t[o].l+1);
t[o].lazy +=c;
return;
}
int mid=(t[o].l+t[o].r)>>1;
pushdown( o,mid-t[o].l+1,t[o].r-mid);
if(r<=mid) updata(l,r,c,ls);
else if(l>mid) updata(l,r,c,rs);
else
{
updata(l,mid,c,ls);
updata(mid+1,r,c,rs);
}
push_up(o);
}
inline ll query(int l,int r,int o)
{
if(t[o].l>=l&&t[o].r<=r)
{
return t[o].x;
}
ll ans=0;
int mid=(t[o].l+t[o].r)>>1;
pushdown(o,mid-t[o].l+1, t[o].r-mid);
if(l>mid) ans+=query(l,r,rs);
else if(r<=mid) ans+=query(l,r,ls);
else{
ans+=query(l,mid,ls)+query(mid+1,r,rs);
}
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
build(1,n,1);
char op[10];
int c,d,v;
while(m--)
{
scanf("%s",op);
if(op[0]=='Q')
{
scanf("%d%d",&c,&d);
printf("%lld\n",query(c,d,1));
}
else
{
scanf("%d%d%d",&c,&d,&v);
updata(c,d,v,1);
}
}
return 0;
}
15
Hint
The sums may exceed the range of 32-bit integers.