分析:这题wa了好多次(看了下discuss好多人也是这样,好题~)。一处是sum值会超int32,要用int64。还有一处是toadd要累加,我不知道是受上一题影响还是怎的..pushdown的时候直接替换了...还有,据说北大oj要用%lld读..
类型:成段更新。容易错. 线段树(貌似这题也能用树状数组做?......)
代码:
//3wa
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define MAXN 100002
#define int64 long long
#define lc e<<1
#define rc e<<1|1
struct node{ int l, r, mid, toadd; int64 v; }a[MAXN*4];
int n;
void pushup(int e) { a[e].v=a[lc].v+a[rc].v; }
void pushdown(int e)
{
int t = a[e].toadd;
if(t) //这里是对的
{
a[e].toadd=0;
a[lc].v+=(int64)(a[lc].r-a[lc].l+1)*t;
a[rc].v+=(int64)(a[rc].r-a[rc].l+1)*t;
// a[lc].toadd=a[rc].toadd=t; //增量是累加的。写上一题 hdu1698 Just a Hook 写傻掉了.
a[lc].toadd+=t;
a[rc].toadd+=t;
}
}
void build(int l, int r, int e)
{
a[e].l=l; a[e].r=r;
if(l==r) scanf("%lld", &a[e].v); //这里没用%lld 又wa了一次....
else
{
a[e].mid=l+((r-l)>>1); //????
build(l, a[e].mid, lc);
build(a[e].mid+1, r, rc);
pushup(e);
}
}
void update(int L, int R, int add, int l, int r, int e)
{
if(L<=l && r<=R)
{
a[e].v+=(int64)(a[e].r-a[e].l+1)*add;
// a[e].toadd=add; //这里也一样!!
a[e].toadd+=add;
}
else
{
pushdown(e);
if(L<=a[e].mid) update(L, R, add, l, a[e].mid, lc);
if(a[e].mid < R) update(L, R, add, a[e].mid+1, r, rc);
pushup(e);
}
}
int64 query(int L, int R, int l, int r, int e)
{
int64 ret=0;
if(L<=l && r<=R)
{
ret+=a[e].v;
}
else
{
pushdown(e); //查询也要推下去
if(L<=a[e].mid) ret+=query(L, R, l, a[e].mid, lc);
if(a[e].mid<R) ret+=query(L, R, a[e].mid+1, r, rc);
pushup(e); //不用。
}
return ret;
}
int main()
{
int q;
scanf("%d%d", &n, &q);
build(1, n, 1);
char t[2];
while(q--)
{
int x, y;
scanf("%s%d%d", t, &x, &y);
if(t[0]=='Q')
{
printf("%lld\n", query(x, y, 1, n, 1)); //poj 用 %lld
}
else
{
int add; scanf("%d", &add);
update(x, y, add, 1, n, 1);
}
}
}