![[ACM_数据结构] HDU 1166 敌兵布阵 线段树 或 树状数组 [ACM_数据结构] HDU 1166 敌兵布阵 线段树 或 树状数组](https://image.shishitao.com:8440/aHR0cHM6Ly9ia3FzaW1nLmlrYWZhbi5jb20vdXBsb2FkL2NoYXRncHQtcy5wbmc%2FIQ%3D%3D.png?!?w=700&webp=1)
#include<iostream>
#include<cstdio>
#include<memory.h>
using namespace std;
int n,C[];
//--------------------------
int lowbit(int x){
return x&-x;
}
int sum(int x){
int ret=;
while(x>){
ret+=C[x];
x-=lowbit(x);
}
return ret;
}
void add(int x,int d){
while(x<=n){
C[x]+=d;
x+=lowbit(x);
}
}
//--------------------------
int main(){
int T;
scanf("%d",&T);
int kases=;
int i,j;
int a;
for(;kases<=T;kases++){
memset(C,,sizeof(C));
scanf("%d",&n);
for(i=;i<=n;i++){
scanf("%d",&a);
add(i,a);
}
char str[];
printf("Case %d:\n",kases);
bool ok=;
while(ok){
scanf("%s",str);
switch(str[]){
case 'Q':
scanf("%d%d",&i,&j);
printf("%d\n",sum(j)-sum(i-));
break;
case 'A':
scanf("%d%d",&i,&j);
add(i,j);
break;
case 'S':
scanf("%d%d",&i,&j);
add(i,-j);
break;
case 'E':
ok=;
break;
default:break;
}
}
}return ;
}
#include<iostream>
#include<cmath>
using namespace std;
#define maxn 100005
class Node{
public:
int l,r;
int add;//附加值
int sum;
}node[maxn];
int getRight(int n){//获得满足2^x>=n的最小x[从0层开始,给编号获得层数]
return ceil(log10(n*1.0)/log10(2.0));
}
void build(int l,int r,int num){//输入区间[1,2^getRight(n)],num=1建树
if(l==r){
node[num].l=node[num].r=l;node[num].add=;node[num].sum=;
return;
}
node[num].l=l;node[num].r=r;node[num].add=;node[num].sum=;
build(l,(l+r)/,num*);
build((l+r)/+,r,num*+);
}
void add(int o,int l,int r,int v){//从o节点开始递归[只要调用时o=1即可]在区间[l,r]全部加v
if(l<=node[o].l && r>=node[o].r){//全覆盖[递归边界]
node[o].add+=v;
}else{
int M=node[o].l+(node[o].r-node[o].l)/;
if(r<=M)add(o*,l,r,v);
else if(l>M)add(o*+,l,r,v);
else{
add(o*,l,M,v);
add(o*+,M+,r,v);
}
}
//维护节点o
if(node[o].l!=node[o].r){//如果区间只是一个元素就不算
node[o].sum=node[*o].sum+node[*o+].sum;
}else node[o].sum=;
node[o].sum+=node[o].add*(node[o].r-node[o].l+);
} //这里addadd是从上往下这条路的累计addadd值[一同回溯记录这条路节点所有add之和,减少了一次回溯累加add值]
//初始时直接令其为0
int sum=;
void ask(int o,int l,int r,int addadd){//从o节点开始递归[只要调用时o=1即可]在区间[l,r]的和
if(l<=node[o].l && r>=node[o].r){//全覆盖[递归边界]
sum+=(node[o].sum+addadd*(node[o].r-node[o].l+));
}else{
int M=node[o].l+(node[o].r-node[o].l)/;
if(r<=M)ask(o*,l,r,node[o].add+addadd);
else if(l>M)ask(o*+,l,r,node[o].add+addadd);
else{
ask(o*,l,M,node[o].add+addadd);
ask(o*+,M+,r,node[o].add+addadd);
}
}
}
int main(){
int T;
scanf("%d",&T);
int kases=;
int i,j;
int a;
for(;kases<=T;kases++){
int N;
scanf("%d",&N);
build(,<<getRight(N),);
for(i=;i<=N;i++){
scanf("%d",&a);
add(,i,i,a);
}
char str[];
printf("Case %d:\n",kases);
bool ok=;
while(ok){
scanf("%s",str);
switch(str[]){
case 'Q':
scanf("%d%d",&i,&j);
sum=;
ask(,i,j,);
printf("%d\n",sum);
break;
case 'A':
scanf("%d%d",&i,&j);
add(,i,i,j);
break;
case 'S':
scanf("%d%d",&i,&j);
add(,i,i,-j);
break;
case 'E':
ok=;
break;
default:break;
}
}
}return ;
}