这题数据很大,注意要__int64 。
其他差不多,
/*
poj 3468
注意标签的作用,注意是+=,才能传递正确的值下去,一定要注意到这定,标签的值
*/
#include <stdio.h>
#include <stdlib.h>
#define MAX 150000
using namespace std;
typedef struct node
{
int s,e;
__int64 mark;
__int64 sum;
node (int a=0,int b=0,__int64 c=0,__int64 d=0):s(a),e(b),mark(c),sum(d){};
}node;
node tree[4*MAX];
__int64 num[MAX];
int flag=0;
/*这里真是坑,注意用__int64才行,什么LONG LONG 都WR __int64 就AC*/
void build (int T,int s,int e)
{
if (s==e)
tree[T] = node(s,e,0,num[flag++]);
else
{
int mid = (s+e)>>1;
build(T<<1,s,mid);
build (T<<1|1,mid +1 ,e);
tree[T]=node (s,e,0,tree[T<<1].sum+tree[T<<1|1].sum);
}
}
void change_down(int T)
{
if (tree[T].mark)
{
tree[T<<1].mark +=tree[T].mark; tree[T<<1|1].mark += tree[T].mark; //标签一定是+=,才能把最终到底是多少
tree[T<<1].sum += (tree[T<<1].e-tree[T<<1].s+1)*tree[T].mark; //的和传递下去
tree[T<<1|1].sum += (tree[T<<1|1].e-tree[T<<1|1].s+1)*tree[T].mark;
tree[T].mark = 0;//记得消除标记 }
}
}
void update(int T,int s,int e,int p)
{
if (s<= tree[T].s&& e>=tree[T].e)
{
tree[T].mark += p;//这里一定要用+= 因为,不断操作,比如+3 +4 那么向下传递时
tree[T].sum += (tree[T].e-tree[T].s+1)*p; //一定是+7,而不是用赋值,这样就变成了
} //传递4了,
else
{
change_down(T);//当前节点是否标记过,是的话,标签下移
int mid = (tree[T].s+tree[T].e)>>1;
if (s<=mid) update(T<<1,s,e,p);
if (e>mid) update (T<<1|1,s,e,p);
tree[T].sum = tree[T<<1].sum+tree[T<<1|1].sum;
}
}
__int64 Query(int T,int s,int e)
{
if (s<=tree[T].s && e>=tree[T].e)
{
return tree[T].sum;
}
else //该区间未包含需要向下,或者未标记也需要向下,
{
change_down(T);
int mid = (tree[T].s + tree[T].e)>>1;
__int64 s1 = 0;
if (s<=mid) s1 += Query(T<<1,s,e);
if (e>mid) s1 += Query(T<<1|1,s,e);
return s1;
}
}
int main ()
{
int n,q;
scanf ("%d%d",&n,&q);
for (int i=0;i<n;++i)
scanf ("%I64d",&num[i]);
flag = 0;
build (1,1,n);
char c[4];int a1,b1,c1;
for (int i=0;i<q;++i)
{
scanf ("%s",&c);//用单个字符会出毛病,所以用串
if (c[0]=='Q')
{
scanf ("%d %d",&a1,&b1);
printf ("%I64d\n",Query(1,a1,b1));
}
else
{
scanf ("%d %d %d",&a1,&b1,&c1);
update(1,a1,b1,c1);
}
}
return 0;
}
/*
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
*/