第一次写关于线段数的题目 初步了解一下
线段树的单点更新.
node表示序号 num为价值(即为里面区间的数的和)
#include<bits/stdc++.h>
using namespace std;
int n,num[50010*3+10],a[50010],b,c;
string s;
void build(int begin,int end,int node)//建立一个线段树
{
if(begin==end)//查到最底下(最基础)的一个
{
num[node]=a[begin];
return;
}
int mid=(begin+end)/2;//中间值 二分
build(begin,mid,node*2);//左孩子
build(mid+1,end,node*2+1);//右孩子
num[node]=num[node*2]+num[node*2+1];//每一个父节点都是俩个子节点的和
}
void update(int begin,int end,int node,int i,int j)//更新数据(j为正则为加,j为负则为减)
{
if(begin==end) //查到i这个数时即begin==end==i
{
num[node]+=j;//更新
return;
}
int mid=(begin+end)/2;//中间值 二分
if(i<=mid)//如果这个数在左边或者中间值这个点
update(begin,mid,node*2,i,j); //查左边的
else//如果这个数在右边
update(mid+1,end,node*2+1,i,j);//查右边的
num[node]+=j;//更新
}
int query(int begin,int end,int node,int i,int j)//查找
{
if(begin==i&&end==j)//找到了这个区间
{
return num[node];
}
int mid=(begin+end)/2;//中间值 二分
if(j<mid+1)//如果都在左边
{
return query(begin,mid,node*2,i,j);//直接查左边
}
else if(i>mid)//如果都在右边
{
return query(mid+1,end,node*2+1,i,j);//直接查右边
}
else//如果俩边都有,则把它分为俩份左边一份,右边一份,进行查找
{
return query(begin,mid,node*2,i,mid)+query(mid+1,end,node*2+1,mid+1,j);
}
}
int main()
{
int t;
cin>>t;
int l=0;
while(t--)
{
l++;
cin>>n;
for(int k=1;k<=n;k++)
{
scanf("%d",&a[k]);//要输入的数太多 用cin输入会超时
}
build(1,n,1);
cout<<"Case "<<l<<":"<<endl;
while(cin>>s)
{
if(s=="End")
break;
cin>>b>>c;
if(s=="Add")
{
update(1,n,1,b,c);
}
else if(s=="Sub")
{
update(1,n,1,b,-c);
}
else
{
int x=query(1,n,1,b,c);
cout<<x<<endl;
}
}
}
return 0;
}