给出一系列操作,更新某一区间上所有数加上一个数,然后求出某一区间上所有数的和。。。
用常规的线段树模版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;
}

浙公网安备 33010602011771号