很久以前的题目再做一遍复习一下。
要点:
1)约定在任何时候 add_num 到达节点的时候就立即更新节点的 sum 值。
2)每次更新节点回溯的时候记得维护节点的 sum 值。
3)执行询问操作的时候,遇到 lazy 标记为1 的时候往下 Push_down,,同时记得第一点
4)遇到符合要求的询问区间时,由于第一条的规定,直接返回 sum 值,而不必加上 区间长度*add_num
好了,以前由于不知道什么时候返回sun 值 和 什么时候加上 区间长度*add_num犯糊涂,加上了第一条的约定,这样就比较明朗了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cstdlib>
using namespace std;
typedef long long LL;
const int MAXN = 100020;
struct node
{
int l,r;
bool lazy;
LL add;
LL sum;
}p[MAXN<<2];
int a[MAXN];
int n,m;
bool init()
{
if(scanf("%d%d",&n,&m)==EOF)return false;
for(int i=1;i<=n;i++)scanf("%d",a+i);
return true;
}
void build(int ic,int l,int r)
{
p[ic].l=l;
p[ic].r=r;
p[ic].lazy=0;
if(l==r)
{
p[ic].sum=a[l];
return;
}
int mid = (l+r)>>1;
build(ic<<1,l,mid);
build(ic<<1|1,mid+1,r);
p[ic].sum=p[ic<<1].sum+p[ic<<1|1].sum;
}
void push_down(int ic)
{
int l = p[ic].l;
int r = p[ic].r;
int lc = ic<<1,rc=ic<<1|1;
p[lc].add+=p[ic].add;
p[rc].add+=p[ic].add;
p[lc].sum += (p[lc].r-p[lc].l+1)*p[ic].add;
p[rc].sum += (p[rc].r-p[rc].l+1)*p[ic].add;
p[ic].sum = p[lc].sum+p[rc].sum;
p[lc].lazy=p[rc].lazy =1;
p[ic].add = 0;
p[ic].lazy =0 ;
}
void update(int ic,int l_up,int r_up,int add_num)
{
int l = p[ic].l;
int r = p[ic].r;
//printf("ic:%d l:%d r:%d l_up:%d r_up:%d\n",ic,l,r,l_up,r_up);
if((l==l_up)&&(r==r_up))
{
p[ic].lazy = 1;
p[ic].add +=add_num;
p[ic].sum +=(r-l+1)*add_num;
// printf("return %d \n",ic);
return;
}
if(p[ic].lazy)push_down(ic);
int mid = (l+r)>>1;
if(l_up>mid)update(ic<<1|1,l_up,r_up,add_num);
else if(r_up<=mid)update(ic<<1,l_up,r_up,add_num);
else
{
update(ic<<1,l_up,mid,add_num);
update(ic<<1|1,mid+1,r_up,add_num);
}
int lc = ic<<1;
int rc = ic<<1|1;
p[ic].sum=p[lc].sum+p[rc].sum;
}
void ADD()
{
int x,y;
int add_num;
scanf("%d%d%d",&x,&y,&add_num);
if(x>y)swap(x,y);
update(1,x,y,add_num);
}
LL do_Query(int ic,int Ql,int Qr)
{
int l = p[ic].l;
int r = p[ic].r;
if(l==Ql&&r==Qr)
{
return p[ic].sum;
}
if(p[ic].lazy)push_down(ic);
int mid = (l+r)>>1;
if(Qr<=mid)return do_Query(ic<<1,Ql,Qr);
else if(mid<Ql)return do_Query(ic<<1|1,Ql,Qr);
else
{
return do_Query(ic<<1,Ql,mid)+do_Query(ic<<1|1,mid+1,Qr);
}
}
void Query()
{
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",do_Query(1,x,y));
}
void op_Tree(int ic)
{
int l = p[ic].l;
int r = p[ic].r;
printf("ic:%d l:%d r:%d sum:%I64d\n",ic,l,r,p[ic].sum);
if(l==r)return;
op_Tree(ic<<1);
op_Tree(ic<<1|1);
}
#define dbug9
void debug()
{
op_Tree(1);
}
void solve()
{
char cmd[10];
memset(p,0,sizeof(p));
build(1,1,n);
#ifdef dbug
debug();
#endif
while(m--)
{
scanf("%s",cmd);
switch(cmd[0])
{
case 'C':ADD();break;
case 'Q':Query();break;
default :cout<<"fuck!"<<endl;
}
}
}
int main()
{
freopen("3468.txt","r",stdin);
while(init())
solve();
return 0;
}