http://acm.hdu.edu.cn/showproblem.php?pid=1166
题目意思很明显,需要多次查询,多次进行修改操作。用线段树做,由于每次只对一个点进行修改,所以数据结构中只需要包含和项,而不必要包含修改标志。
代码如下:
/*
ID: csuchenan
PROG: hduoj 1166 敌兵布阵
LANG: C++
*/
#include
#include
#include
#define MAXN 50005
struct Node{
int left ;
int right;
int nsum ;
}node[3*MAXN + 5] ;
void build(int left , int right , int step) ;
void insert(int pos , int step , int nval) ;
//void update(int left , int right ,int nfalg);
void update(int pos , int nflag , int layer) ;
void query(int left , int right , int layer , int &nsum) ;
int n ;
int main(int argc , char * argv[]){
int test ;
scanf("%d" , &test) ;
int ncase ;
ncase = 1 ;
int i ;
int j ;
int data ;
char str[10] ;
int s ;
int num ;
int nsum ;
while(ncase <= test){
printf("Case %d:\n" , ncase ++) ;
scanf("%d" , &n) ;
build(1 , n , 1) ;
i = 1 ;
while(i <= n){
scanf("%d " , &data) ;
insert(i , 1 , data) ;
i ++ ;
}
while(1){
scanf("%s" , str) ;
if(strcmp(str , "End")==0){
break ;
}
scanf("%d %d" , &s , &num) ;
if(strcmp(str , "Query")==0){
nsum = 0 ;
query(s , num , 1 , nsum) ;
printf("%d\n" , nsum) ;
continue ;
}
if(strcmp(str , "Add") == 0){
update(s , num , 1) ;
continue ;
}
if(strcmp(str , "Sub") == 0){
update(s , -num , 1) ;
continue ;
}
}
}
return 0 ;
}
void build(int left , int right , int step){
node[step].left = left ;
node[step].right = right ;
node[step].nsum = 0 ;
if(left == right){
return ;
}
int mid = (left + right) / 2 ;
int ls = step * 2 ;
int rs = step * 2 + 1 ;
build(left , mid , ls) ;
build(mid + 1 , right , rs) ;
}
void insert(int pos , int step , int nval){
//如果刚好区间相同,则直接插入,修改nsum的值
if(node[step].left == pos && node[step].right == pos){
node[step].nsum += nval ;
return ;
}
//否则,包含在该区间内,故而要将其的值累加到区间上,然后分左右区间
node[step].nsum += nval ;
int mid = (node[step].left + node[step].right) / 2 ;
int nstep ;
//分到左则
if(pos <= mid){
nstep = step * 2 ;
insert(pos , nstep , nval) ;
return ;
}
//分到右侧
nstep = step * 2 + 1 ;
insert(pos , nstep , nval) ;
return ;
}
void update(int pos , int nflag , int layer){
if(node[layer].left == pos && node[layer].right == pos){
node[layer].nsum += nflag ;
return ;
}
//对于该区间上的值直接进行累加
node[layer].nsum += nflag ;
int mid = (node[layer].left + node[layer].right) / 2 ;
int nlayer ;
//分到左侧
if(pos <= mid){
nlayer = layer * 2 ;
update(pos , nflag , nlayer) ;
return ;
}
//右侧
nlayer = layer * 2 + 1 ;
update(pos , nflag , nlayer) ;
return ;
}
void query(int left , int right , int layer , int &nsum){
if(node[layer].left == left && node[layer].right == right){
nsum += node[layer].nsum ;
return ;
}
int mid = (node[layer].left + node[layer].right) / 2 ;
int nlayer ;
if(right <= mid){
nlayer = layer * 2 ;
query(left , right , nlayer , nsum) ;
return ;
}
if(left > mid){
nlayer = layer * 2 + 1 ;
query(left , right , nlayer , nsum) ;
return ;
}
nlayer = layer * 2 ;
query(left , mid , nlayer , nsum) ;
nlayer ++ ;
query(mid + 1 , right , nlayer , nsum) ;
return ;
}