您的位置:首页 > 其它

hdu1166 敌兵布阵(线段树入门题)

2015-02-15 17:31 274 查看
#include<iostream>
using namespace std;

const int maxn = 50001;

struct tree
{
int left,right;
int sum;
}node;

tree t[maxn * 3]; //结点数
int a[maxn]; //元素的值

void build(int num,int left,int right)  //num表示序号
{
t[num].left = left;
t[num].right = right;
if(left == right)
{
t[num].sum = a[left];
return;
}
else
{
int mid = (left + right) >> 1;
build(num*2,left,mid); //左子结点
build(num*2 + 1,mid+1,right); //右子结点
t[num].sum = t[num*2].sum + t[num*2+1].sum;//父结点的值等于两个子结点的值
}
}

void updata(int num,int left,int right,int pos,int add)
{
t[num].sum += add;
if(left == right && left == pos) //如果找到该位置就退出
{
return ;
}
int mid = (left + right) >> 1;
if(pos <= mid)  //递归左子树
updata(num * 2,left,mid,pos,add);
else  //递归右子树
updata(num * 2 + 1,mid+1,right,pos,add);
}

int query(int num,int left,int right,int num1,int num2)  //查询区间[num1,num2]
{
if(left == num1 && right == num2) //如果找到区间就返回
{
return t[num].sum;
}
int mid = (left + right) >> 1; //二分
if(num2 <= mid)  //左子树
{
return query(num * 2,left,mid,num1,num2);
}
if(num1 >= mid + 1) //右子树
{
return query(num * 2 + 1,mid + 1,right,num1,num2);
}
return query( num * 2, left, mid, num1, mid ) + query( num * 2 + 1, mid + 1, right, mid + 1, num2 ); //如果垮区间的话
}

int main()
{
int t,n;
while( scanf("%d", &t ) != EOF )
{
for( int j = 1; j <= t; j ++ )
{
printf( "Case %d:\n", j );
scanf( "%d", &n );
for( int i = 1; i <= n; i ++ )
{
scanf( "%d", &a[i] );
}
build( 1, 1, n );
char str[10];
int a,b;
scanf( "%s", str );
while( str[0] != 'E' )
{
scanf( "%d%d", &a, &b );
if( str[0] == 'A' )
updata( 1, 1, n, a, b );
else if( str[0] == 'S' )
updata( 1, 1, n, a, -b );
else
printf( "%d\n", query( 1, 1, n, a, b ) );
scanf( "%s", str );
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: