/^&%$#@$%&_)(*&^%%$%%Y%FD%$^U&&^U*&(()*&^%$##@$%^&*(&^%$#@$%^&*
**************************************************************************************************
刚刚开始学习线段树了。挣扎了很久才有一点理解,主要还是因为自己太渣了。既然智商不够用,只能用时间来补救了。
当然,因为线段树,才对堆式存储真正有了一些理解。我就不说我堆排序还没敲出来了吧?
其实我真的很喜欢这样去学习啊。
言归正传。这是第一次敲线段树。其实还是参考了某神的代码风格,因为也就粗浅地看了一点线段树的文章,并不知道具体是要去写哪些东西来实现。
原谅我吧。然后自己死磕了N久。
对加减一个数后的updata, 我是直接先对那个叶子节点操作,然后递归地pushup的过程。你们是直接都一路下来加减那个数
其实我是懒得在sub传参的时候加一个负号吧。。
哎呀先这样。好好加油了!
**************************************************************************************************
!#@$%^&*()_)(*&^%$#@!@#$^&(*&^%$#@!@%^&*(PLKUTRGFED@$%^&*()*&^%$#Q/
# include<stdio.h>
const int maxn=50005;
int a[maxn<<2];
int b[maxn];//b[i]表示第i个点在a中的位置
int find(int i, int n)//寻找某点在a中的位置
{
int m;
int l=1, r=n, rt=1;
while(l!=r)
{
m=(l+r)>>1;
if(i<=m) {r=m; rt=rt<<1;}
else {l=m+1; rt=rt<<1|1;}
}
return rt;
}
void PushUp(int rt)
{
a[rt]=a[rt<<1]+a[rt<<1|1];
}
void create(int l, int r, int rt)//建树
{
if(l==r)return;
int m=(l+r)>>1;
create(l, m, rt<<1);
create(m+1, r, rt<<1|1);
PushUp(rt);
}
void updata(int i, int l, int r,int rt)//更新节点
{
if(l==r) return;
int m=(l+r)>>1;
if(i<=m) updata(i, l, m, rt<<1);
else updata(i, m+1, r, rt<<1|1);
PushUp(rt);
}
int Query(int i, int j, int l, int r, int rt)//询问
{
if(i<=l && r<=j) return a[rt];
int m=(l+r)>>1;
int ans=0;
if(i<=m)
ans+=Query(i, j, l, m, rt<<1);
if(j>m)
ans+=Query(i, j, m+1, r, rt<<1|1);
return ans;
}
int main()
{
int T, i, j, n, ai, l, r, m, ans;
char s[5];
scanf("%d", &T);
for(int o=1; o<=T; o++)
{
printf("Case %d:\n", o);
scanf("%d", &n);
for(i=1; i<=n; i++)
{
scanf("%d", &ai);
b[i]=find(i, n);
a[b[i]]=ai;
}
create(1, n, 1);
while(scanf("%s", s))
{
if(s[0]=='E') break;
if(s[0]=='A')
{
scanf("%d%d", &i, &j);
a[b[i]]+=j;
updata(i, 1, n, 1);
}
else if(s[0]=='S')
{
scanf("%d%d", &i, &j);
a[b[i]]-=j;
updata(i, 1, n, 1);
}
else
{
scanf("%d%d", &i, &j);
ans=Query(i, j, 1, n, 1);
printf("%d\n", ans);
}
}
}
return 0;
}