成段更新
这题数据很大,注意要__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 ",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 */