线段树的基本操作,具体看代码注释。
View Code
#include <iostream>
#include
<string>

using namespace std;
const int MAX = 50005;

struct Tree
{
int left; int right; int num;
}tr[MAX
*3];
int arr[MAX],n,t,a,b,ans;
string cmd;

void build(int l,int r,int now) // 构造线段树
{
tr[now].left
= l; tr[now].right = r;

if(l == r) {tr[now].num = arr[l]; return;} //编号为now的叶子节点保存第now个兵营的士兵数

int mid = (l + r)>>1;

build(l,mid,now
<<1); // 递归构造左子树
build(mid+1,r,(now<<1)+1); // 递归构造右子树

tr[now].num
= tr[now<<1].num + tr[(now<<1)+1].num; // 父亲节点保存左右子树的士兵之和
}

void modify(int l,int r,int now)
{
if(tr[now].left == tr[now].right) {tr[now].num += b; return;} // 找到要修改的兵营叶子节点

int mid = (tr[now].left + tr[now].right)>>1;

if(a <= mid) // 要插入的兵营在左子树
{
modify(l,r,now
<<1);
}
else if(a > mid) // 要插入的的兵营在右子树
{
modify(l,r,(now
<<1)+1);
}

tr[now].num
= tr[now<<1].num + tr[(now<<1)+1].num; // 父亲节点保存左右子树的士兵之和
}

void query(int sta,int end,int now) //查询[sta,end]之间的士兵数
{
if(sta == tr[now].left && end == tr[now].right) {ans += tr[now].num; return;}

int mid = (tr[now].left + tr[now].right) >> 1;

if(end <= mid)
{
query(sta,end,now
<<1);
}
else if(sta > mid)
{
query(sta,end,(now
<<1)+1);
}
else
{
query(sta,mid,now
<<1);
query(mid
+1,end,(now<<1)+1);
}
}


int main()
{
int i;
scanf(
"%d",&t);

for(int c = 1;c <= t;++c)
{
scanf(
"%d",&n);
for(i = 1;i <= n;++i) scanf("%d",&arr[i]);

build(
1,n,1);

printf(
"Case %d:\n",c);
while(true)
{
cin
>>cmd;
if(cmd[0] == 'E') break;
scanf(
"%d %d",&a,&b);

if(cmd[0] == 'A')
{
modify(
1,n,1);
}
else if(cmd[0] == 'S')
{
b
= -b;
modify(
1,n,1);
}
else
{
ans
= 0;
query(a,b,
1);
printf(
"%d\n",ans);
}
}
}
return 0;
}
posted on 2011-04-09 13:11  c++fans  阅读(294)  评论(0编辑  收藏  举报