hdu1166-敌兵布阵
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166
线段树的操作: 建立 + 单点改变 + 区间求和 (random为区间和)
#include
#include
#include
#define maxn 50005
int Num ;
int val[maxn] ;
struct line
{
int left,right ;
int sum ; /**random为总和*/
}a[maxn*4];
void buil ( int l , int r , int n ) /**区间建立*/
{
int mid ;
a[n].left = l ;
a[n].right = r ;
if( l == r ) {
a[n].sum = val[l-1] ;
return ;
}
mid = ( l + r ) / 2 ;
buil( l , mid , 2*n ) ;
buil( mid+1 , r , 2*n+1 ) ;
a[n].sum = a[2*n].sum + a[2*n+1].sum ;
}
void addsub( int i , int j )
/**这次没递归,因为我只对点i一个点进行操作,那么保证二分区间里有i就可以了,没必要递归*/
{
int ll , rr , mm, n ;
ll = 1 ;
rr = Num ;
n = 1 ;
while( ll != rr ){
/**printf( " ll rr %d %d\n",ll ,rr );*/
if( ll <= i && i <= rr ){
a[n].sum += j ;
mm = ( ll + rr ) / 2 ;
if( mm >= i ){
rr = mm ;
n = 2*n ;
}
else{
ll = mm + 1 ;
n = 2*n + 1 ;
}
}
}
a[n].sum += j ;
}
int quer ( int i , int j ,int start )
{
/**这里是对一个区间操作,那么我就要二分区间判断区间的包含,所以就递归了*/
int mid ;
int sum = 0 ;
if( a[start].left == i && a[start].right== j ){
return a[start].sum ;
}
mid = ( a[start].left + a[start].right )/2 ;
if( mid >= j ){
sum += quer( i , j , 2*start ) ;
}
else{
if( mid < i ){
sum += quer( i , j , 2*start+1 ) ;
}
else{
sum += quer( i , mid , 2*start ) ;
sum += quer ( mid+1 , j , 2*start+1 ) ;
}
}
return sum ;
}
int main()
{
int T , t_ ;
int n_ ;
int i , j ;
char dir[10] ;
scanf( "%d", &T ) ;
t_ = 0 ;
while ( t_ < T ){
/*t_++;*/printf( "Case %d:\n" , ++t_ ) ;
scanf( "%d" , &Num ) ;
n_ = 0 ;
while( n_ < Num ){
scanf( "%d",&val[n_ ++] ) ;
}
getchar() ;
/**这个scanf的输入要灰常小心,如果前面用来scanf而且还有一些多余空格神马的输入,就要吃掉*/
buil(1 , Num , 1) ;
while(scanf( "%s" , dir ) && strcmp( dir , "End" ) ){
scanf( "%d%d" , &i , &j ) ;
getchar();
if( !strcmp( "Query" , dir ) ){
printf( "%d\n" , quer( i , j , 1 ) ) ;
}
else{
if( !strcmp( "Add" , dir ) ){
addsub( i , j ) ;
}
else {
addsub( i , 0-j ) ;
}
}
}
}
return 0;
}