线段树水题。
有三种操作,x点加sum人,x点减sum人,求出 x 到 y 的和。
每个父节点加一个节点保存下面子树的和即可。减人的时候,增加负的值即可。1Y,嗨皮~
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
#include <climits>
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define MID(x,y) ( (x+y)>>1 )
using namespace std;
const int MAX = 50010;
struct Tnode{int sum,l,r;};
Tnode node[MAX*4];
int num[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 = num[l];
return ;
}
int mid = MID(l,r);
Build(L(t),l,mid);
Build(R(t),mid,r);
node[t].sum = node[R(t)].sum + node[L(t)].sum;
}
void Updata(int t,int l,int r,int sum)
{
if( node[t].l == l && node[t].r == r )
{
node[t].sum += sum;
return ;
}
int mid = MID(node[t].l,node[t].r);
if( l >= mid )
Updata(R(t),l,r,sum);
else
if( r <= mid )
Updata(L(t),l,r,sum);
else
{
Updata(L(t),l,mid,sum);
Updata(R(t),mid,r,sum);
}
node[t].sum += sum;
}
int Query(int t,int l,int r)
{
if( node[t].l == l && node[t].r == r )
return node[t].sum;
int mid = MID(node[t].l,node[t].r);
if( l >= mid )
return Query(R(t),l,r);
else
if( r <= mid )
return Query(L(t),l,r);
else
return Query(L(t),l,mid) + Query(R(t),mid,r);
}
int main()
{
int ind = 1,ncases,n,x,y;
char s[10];
scanf("%d",&ncases);
while( ncases-- )
{
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d",&num[i]);
init();
Build(1,0,n+1);
printf("Case %d:\n",ind++);
while( scanf("%s",s) && strcmp(s,"End") )
{
scanf("%d%d",&x,&y);
if( s[0] == 'A' )
Updata(1,x-1,x,y);
else
if( s[0] == 'S' )
Updata(1,x-1,x,-y);
else
printf("%d\n",Query(1,x-1,y));
}
}
return 0;
}