HDU 1166 敌兵布阵【线段树】

线段树的基本操作,具体看代码注释。
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 ;
}

你可能感兴趣的:(HDU)