#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int N=5e4+10;
int tree[N],A[N];//A[]为原数组
int n;//n为要用到的规模
inline int lowbit(int x) { //求取转化为二进制时最低位1+一串0的数
return x&(-x);
}
inline string readS()//快读字符串
{
char ch = getchar();
string st1 = "";
while (!(((ch >= 'a') && (ch <= 'z')) || ((ch >='A') && (ch <='Z'))))
ch = getchar();
while ((((ch >= 'a') && (ch <= 'z')) || ((ch >='A') && (ch <='Z'))))
st1 += ch, ch = getchar();
return st1;
}
inline int read(){//快读 不要在与同一行有string的情况下使用
char ch=getchar();
int s=0,w=1;
while(ch<'0' || ch>'9'){
if(ch=='-') w*=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){//不要写成|| !
s=ch-'0'+(s<<3)+(s<<1);
ch=getchar();//不要忘记!
}
return s*w;
}
void updata(int idx,int delta) { // 单点更新 对原数组直接修改,对树状数组增加向上升纯 注意这里的delta是变化值而不是修改后的值
A[idx]+=delta;
while(idx <= n) {
tree[idx] += delta;
idx += (idx & -idx);
}
}
int sum(int idx) { //求前缀和 累加向下升纯 Sum(1~idx)
int s = 0;
while(idx > 0) {
s += tree[idx];
idx -= (idx & -idx);
}
return s;
}
int sumRange(int i,int j) { //区间求和sum[i,j] 虽然说有些情况下会多运算几次,但是已经很优秀了
int res = 0;
i --;
while(i != j) {
res = res + tree[j] - tree[i];
i -= lowbit(i);
j -= lowbit(j);
}
return res;
}
int main() {
int T=read();
for(int i=1; i<=T; i++) { //T组数据
cout<<"Case "<<i<<":"<<endl;
memset(tree,0,sizeof(tree));
n=read();
for(int j=1; j<=n; j++) {
int v;cin>>v;
updata(j,v);
}
string input;
while(1) {
input=readS();
if(input[0]=='E') break;
int x=read(),y=read();
if(input[0]=='A') updata(x,y);
else if(input[0]=='S') updata(x,-y);
else cout<<sumRange(x,y)<<endl;
}
}
return 0;
}
POJ 1166 敌兵布阵 单点更新 区间求和 树型数组
最新推荐文章于 2022-03-20 12:39:28 发布