题意是初始化炮兵人数,然后对其进行一系列修改,最后查询区间人数和
用一般数组做会超时,改用线段树
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int num[50050];
class tree
{public:
int l,r,data; //data存每棵树区间内的人数
}tree[150050];
void insert(int n,int l,int r) //n表示第n个数,从1开始不停地初始化树
{tree[n].l=l; //初始化每棵树代表的左右区间
tree[n].r=r;
if(l==r)
tree[n].data=num[l]; //num数组存各个兵营的人数
else
{
int mid=(l+r)>>1; //递归继续初始化左右子树
insert(2*n,l,mid);
insert(2*n+1,mid+1,r);
tree[n].data=tree[2*n].data+tree[2*n+1].data;
}
}
void modify(int n,int x,int temp)
{if(tree[n].l==tree[n].r) //修改时,从第一棵树传进来往下搜,然后从下往上维护data
{
tree[n].data+=temp;
return ;
}
int mid;
mid=(tree[n].l+tree[n].r)/2;
if(x<=mid) //x表示第几个兵营,因此用X来和mid做比较从而选择在左子树还是右子树
modify(n*2,x,temp);
else
modify(n*2+1,x,temp);
tree[n].data+=temp;
}
int query(int n,int a,int b)
{if(tree[n].l==a&&tree[n].r==b)//查询同修改类似,先自上而下,然后从下往上返回data值
return tree[n].data;
else
{
int mid=(tree[n].l+tree[n].r)/2; //选择所查询区间在左子树还是右子树,或者是由左右子树部分区间之和
if(a>mid)
return query(n*2+1,a,b);
else
{
if(b<=mid)
return query(n*2,a,b);
else
return query(n*2,a,mid)+query(n*2+1,mid+1,b);
}
}
}
int main()
{int t,key=1;
//freopen("E:\\in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{printf("Case %d:\n",key++);
memset(num,0,sizeof(num));
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
insert(1,1,n);
//char str[6];
string str;
int a,b;
while(cin>>str)
{if(str=="End")
break;
scanf("%d%d",&a,&b);
if(str=="Add")
{
modify(1,a,b);
}
if(str=="Sub")
{
modify(1,a,-1*b);
}
if(str=="Query")
{
printf("%d\n",query(1,a,b));
}
}
}
return 0;
}