解析:线段树的单点更新,线段树套用线段树的模板。、
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 50005;
int s[N << 2], L[N << 2], R[N << 2];
int a[N];
void build(int u,int l,int r) {
if(l == r) {
R[u] = L[u] = l;
s[u] = a[l];
return ;
}
int mid = (l + r) / 2;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
L[u] = l;
R[u] = r;
s[u] = s[u*2] + s[u*2+1];
}
void modify(int u,int x,int v) {
if(R[u] == x && L[u] == x) { //叶子节点
s[u] = s[u] + v;
return ;
}
//非叶子节点
int mid = (L[u] + R[u]) / 2;
if(x <= mid) {
modify(u*2,x,v);
}else {
modify(u*2+1,x,v);
}
s[u] = s[u] + v;
}
int query(int u,int l,int r) {
if(l <= L[u] && R[u] <= r) {
return s[u];
}
int mid = (L[u] + R[u]) / 2;
if(r <= mid) { //如果左区间有涉及
return query(u*2,l,r); //则递归左边子树
}else if(l > mid) { //如果右区间有涉及
return query(u*2+1,l,r); //则递归右字数
}else { //如果都没有涉及
return query(u*2,l,r) + query(u*2+1,l,r);
}
}
int main() {
int T,n,cas = 1;
int l,r;
int x,v;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
for(int i = 1; i <= n; i++) {
scanf("%d",&a[i]);
}
memset(s,0,sizeof(s));
L[1] = 1;
R[1] = n;
build(1,L[1],R[1]);
char cmd[20];
printf("Case %d:\n",cas++);
while(scanf("%s",cmd) != EOF) {
if(cmd[0] == 'Q') {
scanf("%d%d",&l,&r);
printf("%d\n",query(1,l,r));
}else if(cmd[0] == 'A') {
scanf("%d%d",&x,&v);
modify(1,x,v);
}else if(cmd[0] == 'S') {
scanf("%d%d",&x,&v);
modify(1,x, -v);
}else if(cmd[0] == 'E') {
break;
}
}
}
return 0;
}
本文介绍了一种基于线段树的数据结构实现方法,并通过一个具体的案例展示了如何使用线段树进行单点更新操作。文章提供了完整的代码示例,包括初始化、修改及查询等关键步骤。
750

被折叠的 条评论
为什么被折叠?



