题目描述,详见HDU 1166;
线段树的上手题,主要是用来熟悉和理解建树和查询的过程。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
const int MAXM=50005;
const int MAXN=140001;
struct node
{
int l,r;
int sum;
};
int n;
int a[MAXM];
int sum1;
struct node t[MAXN];
void build_tree(int l,int r,int num)
{
if (l==r)
{
t[num].l=l;
t[num].r=r;
t[num].sum=a[l];
return ;
}
int mid=(l+r)/2;
build_tree(l,mid,num*2);
build_tree(mid+1,r,num*2+1);
t[num].l=l;
t[num].r=r;
t[num].sum=t[num*2].sum+t[num*2+1].sum;
return ;
}
void query(int l,int r,int num)
{
if (t[num].l>=l&&t[num].r<=r)
{
sum1+=t[num].sum;
return ;
}
int mid=(t[num].l+t[num].r)/2;
if (l>mid) query(l,r,num*2+1);
else if (r<=mid) query(l,r,num*2);
else
{
query(l,r,num*2);
query(l,r,num*2+1);
}
}
void add(int x,int j,int num)
{
t[num].sum+=j;
if (t[num].l==x&&t[num].r==x) return ;
int mid=(t[num].l+t[num].r)/2;
if (x>mid) add(x,j,num*2+1);
else if (x<=mid) add(x,j,num*2);
}
void sub(int x,int j,int num)
{
t[num].sum-=j;
if (t[num].l==x&&t[num].r==x) return ;
int mid=(t[num].l+t[num].r)/2;
if (x>mid) sub(x,j,num*2+1);
else if (x<=mid) sub(x,j,num*2);
}
int main()
{
int T;
scanf("%d",&T);
int p=1;
while(p)
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(t,0,sizeof(t));
build_tree(1,n,1);
string s;
int i,j;
printf("Case %d:\n",p);
while(cin>>s)
{
if (s=="End") break;
cin>>i>>j;
if (s=="Query") {sum1=0; query(i,j,1);printf("%d\n",sum1); }
if (s=="Add") {add(i,j,1); }
if (s=="Sub") {sub(i,j,1); }
}
if (p==T) break;
p++;
}
return 0;
}