题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166
题意:给出一个n个数字,进行2种操作,更改一个数字大小或者询问一个区间所有数字的和
思路:线段树典型的单点更新,区间询问,用树状数组也可以实现,s数组要从1开始,一时没注意查了好久
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 500030
using namespace std;
struct Tree
{
int right,left,date;
}tree[maxn*3];
int s[maxn];
char op[10];
void build(int root,int l,int r)
{
tree[root].left=l;
tree[root].right=r;
if (l==r)
{
tree[root].date=s[l];
return;
}
int mid=(l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
tree[root].date=tree[root<<1].date+tree[root<<1|1].date;
}
void update(int root,int p,int val)
{
if (p>=tree[root].left && p<=tree[root].right)
{
tree[root].date+=val;
if (tree[root].left==tree[root].right) return;
int mid=(tree[root].left+tree[root].right)>>1;
update(root<<1,p,val);
update(root<<1|1,p,val);
}
return;
}
int que(int root,int l,int r)
{
int mid=(tree[root].left+tree[root].right)>>1;
if (l==tree[root].left && r==tree[root].right) return tree[root].date;
else if (r<=mid) return que(root<<1,l,r);
else if (l>mid) return que(root<<1|1,l,r);
else return que(root<<1,l,mid)+que(root<<1|1,mid+1,r);
}
int main()
{
int t,n,cas=0;
scanf("%d",&t);
while (t--)
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
}
build(1,1,n);
printf("Case %d:\n",++cas);
while (scanf("%s",&op) && op[0]!='E')
{
int a,b;
scanf("%d%d",&a,&b);
if (op[0]=='Q') printf("%d\n",que(1,a,b));
else if (op[0]=='A') update(1,a,b);
else if (op[0]=='S') update(1,a,-b);
else break;
}
}
}