给出一系列操作,更新某一区间上所有数加上一个数,然后求出某一区间上所有数的和。。。
用常规的线段树模版TLE。。。数据量太大,这里有个办法是当求出某一区间上要加某个数时,用一个新变量来保存当前增量,不往下更新了。。。
然后再下次更新或者查询时候每次到一个t都进行对增量的更新,否则就一直维持这t上的增量,这样的好处是避免了不必要的更新,因为没必要每次都把某个区间
计算出它的和,只是根据需要时候再计算...
#include <cmath> #include <cstdio> #include <cstdlib> #include <iostream> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <stack> #include <climits> #define MID(x,y) ((x+y)>>1) #define L(x) (x<<1) #define R(x) (x<<1|1) using namespace std; const int MAX = 100010; struct Tnode{__int64 sum,a; int l,r;}; Tnode node[MAX*4]; int v[MAX]; void init() { memset(node,0,sizeof(node)); } void build(int t,int l,int r) { node[t].l = l; node[t].r = r; if( l == r - 1 ) { node[t].sum = v[l]; return ; } int mid = MID(l,r); build(R(t),mid,r); build(L(t),l,mid); node[t].sum = node[L(t)].sum + node[R(t)].sum; } void update(int t,int l,int r,__int64 sum) { if( node[t].l == l && node[t].r == r )//当前区间不往下更新,当前区间所有数都要增加增量a { node[t].a += sum; node[t].sum += sum * ( r - l ); return ; } if( node[t].a )//否则的话开始更新这个增量a,往下传递 { node[R(t)].a += node[t].a; node[L(t)].a += node[t].a; node[R(t)].sum += node[t].a*(node[R(t)].r - node[R(t)].l); node[L(t)].sum += node[t].a*(node[L(t)].r - node[L(t)].l); node[t].a = 0; } int mid = MID(node[t].l,node[t].r); if( l >= mid ) update(R(t),l,r,sum); else if( r <= mid ) update(L(t),l,r,sum); else { update(L(t),l,mid,sum); update(R(t),mid,r,sum); } node[t].sum = node[L(t)].sum + node[R(t)].sum; } __int64 get(int t,int l,int r) { if( node[t].l == l && node[t].r == r ) return node[t].sum; if( node[t].a )//查询时候同样要帮忙更新这个a { node[R(t)].a += node[t].a; node[L(t)].a += node[t].a; node[R(t)].sum += node[t].a*(node[R(t)].r - node[R(t)].l); node[L(t)].sum += node[t].a*(node[L(t)].r - node[L(t)].l); node[t].a = 0; } int mid = MID(node[t].l,node[t].r); if( l >= mid ) return get(R(t),l,r); else if( r <= mid ) return get(L(t),l,r); else return get(L(t),l,mid) + get(R(t),mid,r); } int main() { int n,m,x,y; __int64 z; char s[5]; while( ~scanf("%d%d",&n,&m) ) { for(int i=0; i<n; i++) scanf("%d",&v[i]); init(); build(1,0,n+1); while( m-- ) { scanf("%s",s); if( s[0] == 'Q' ) { scanf("%d%d",&x,&y); printf("%I64d\n",get(1,x-1,y)); } else { scanf("%d%d%I64d",&x,&y,&z); if( z == 0 ) continue; update(1,x-1,y,z); } } } return 0; }