您的位置:首页 > 其它

HDU 1166 敌兵布阵【线段树】

2011-04-09 13:11 316 查看
线段树的基本操作,具体看代码注释。
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: