题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166
中文题目,不需要翻译题目,很单纯的题意,就是快速求区间和。
单点更新在线段树里是最基础的东西,纯属总结模板
1.将子节点更新到父节点
inline void pushup(int rt) //内联提高速度10ms
{
sum[rt] = sum[LS] + sum[RS];
}
2.建树
void build(int l,int r,int rt)
{
if(l == r)
{
scanf ("%d",&sum[rt]);
return ;
}
int m = (l + r) >> 1;
build(LSON);
build(RSON);
pushup(rt); //建完后更新结点
}
3.更新点
void update(int p,int add,int l,int r,int rt)
{
if(l == r)
{
sum[rt] += add;
return ;
}
int m = (l + r) >> 1;
if(p <= m)
update(p,add,LSON);
else
update(p,add,RSON);
pushup(rt); //每次更新子叶便向上更新结点
}
4.求区间和
int query(int ql,int qr,int l,int r,int rt)
{
if(l >= ql && r <= qr)
return sum[rt];
int m = (l + r) >> 1;
int ret = 0;
if(ql <= m)
ret += query(ql,qr,LSON);
if(qr > m)
ret += query(ql,qr,RSON);
return ret;
}
最后,AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#define LS rt << 1
#define RS rt << 1 | 1
#define LSON l,m,rt << 1
#define RSON m + 1,r,rt << 1 | 1
#define MAX 50000
using namespace std;
int sum[MAX << 2];
inline void pushup(int rt) //内联提高速度10ms
{
sum[rt] = sum[LS] + sum[RS];
}
void build(int l,int r,int rt)
{
if(l == r)
{
scanf ("%d",&sum[rt]);
return ;
}
int m = (l + r) >> 1;
build(LSON);
build(RSON);
pushup(rt);
}
void update(int p,int add,int l,int r,int rt)
{
if(l == r)
{
sum[rt] += add;
return ;
}
int m = (l + r) >> 1;
if(p <= m)
update(p,add,LSON);
else
update(p,add,RSON);
pushup(rt);
}
int query(int ql,int qr,int l,int r,int rt)
{
if(l >= ql && r <= qr)
return sum[rt];
int m = (l + r) >> 1;
int ret = 0;
if(ql <= m)
ret += query(ql,qr,LSON);
if(qr > m)
ret += query(ql,qr,RSON);
return ret;
}
int main()
{
int N;
int CASE = 1;
scanf ("%d",&N);
while(N--)
{
int n;
printf ("Case %d:\n",CASE++);
scanf ("%d",&n);
build(1,n,1);
char s[10];
while(scanf ("%s",s),strcmp(s,"End"))
{
int a, b;
scanf ("%d%d",&a,&b);
if(!strcmp(s,"Add"))
{
update(a,b,1,n,1);
}else if(!strcmp(s,"Sub"))
{
update(a,-b,1,n,1);
}else if(!strcmp(s,"Query"))
{
printf ("%d\n",query(a,b,1,n,1));
}
}
}
return 0;
}