hdu1698 线段树

题目链接:Just a Hook

分析:开始学习线段树了,好激动!改了好半天,终于A了。今天写了这个线段树,感觉又有新的体会了。主要是修改和查找。

修改函数Update():在修改区间的时候,如果正好和区间对应,则改变当前点的cover值,如果不对应,则要修改的区间必是当前区间的子区间,再当前区间的两个子区间修改就行了,关键点是:先将当前区间cover值赋给它的两个子区间,同时当前区间的cover值要赋零,表示当前区间里的保存的值不是同一个值。

查找函数Search():查找到当前区间cover值不为0时,就可以返回了,返回seg_tree[id].cover * (r - l),否则继续查找。

 

代码
   
     
#include < stdio.h >
#include
< stdlib.h >
#define NN 100000
struct node{
int l, r, cover;
}seg_tree[NN
* 8 ];


void Init( int l, int r, int id){
seg_tree[id].l
= l;
seg_tree[id].r
= r;
seg_tree[id].cover
= 1 ;
if (r - l <= 1 ){
return ;
}

int mid = (l + r) >> 1 ;
Init(l, mid, id
* 2 );
Init(mid, r, id
* 2 + 1 );
}

void Update( int l, int r, int key, int id){
if (seg_tree[id].l == l && seg_tree[id].r == r){
seg_tree[id].cover
= key;
return ;
}
/* 这个地方关键,要将当前值分别赋给它的两个子区间,自己置零 */
if (seg_tree[id].cover != 0 ){
seg_tree[id
* 2 ].cover = seg_tree[id].cover;
seg_tree[id
* 2 + 1 ].cover = seg_tree[id].cover;
seg_tree[id].cover
= 0 ;
}

int mid = (seg_tree[id].l + seg_tree[id].r) >> 1 ;

if (r <= mid){
Update(l, r, key, id
* 2 );
}
else if (l >= mid){
Update(l, r, key, id
* 2 + 1 );
}
else {
Update(l, mid, key, id
* 2 );
Update(mid, r, key, id
* 2 + 1 );
}
}

int Search( int l, int r, int id){
/* 这个地方也是关键 */
if (seg_tree[id].cover > 0 ){
return seg_tree[id].cover * (r - l);
}

int mid = (seg_tree[id].l + seg_tree[id].r) >> 1 ;

if (r <= mid){
return Search(l, r, id * 2 );
}
else if (l >= mid){
return Search(l, r, id * 2 + 1 );
}
else {
return Search(l, mid, id * 2 ) + Search(mid, r, id * 2 + 1 );
}
}
int main()
{
int T, it, ans, Q, N, x, y, z;
scanf(
" %d " , & T);
for (it = 1 ; it <= T; it ++ ){
scanf(
" %d%d " , & N, & Q);
Init(
0 , N, 1 );
while (Q -- ){
scanf(
" %d%d%d " , & x, & y, & z);
Update(x
- 1 , y, z, 1 ); /* 区间[x-1,x]表示点x */
}

ans
= Search( 0 , N, 1 );
printf(
" Case %d: The total value of the hook is %d.\n " , it, ans);
}

// system("pause");
return 0 ;
}

 

你可能感兴趣的:(HDU)