您的位置:首页 > 其它

【解题报告】 HDU 1698 Just a Hook 线段树 (线段替换) 插线问线 + 延时标记

2012-08-10 12:12 501 查看
// HDU 1698 Just a Hook 线段树(线段替换)插线插线+ 延时标记
// 延时标记:起一个缓冲的作用,第一次遇到的更新先不更新到底,等下一次更新或者查询的时候再更新到位。
// 因此线段树结构中的区间和 并不是实际值。
// 此处的更新到位是指 本次更新或查询所需的最后一层(因为我查的不是点,而是区间),并非到最底层
// 延时标记下沉的前提:线段树结构中遇到了一个区间完全的包含于待更新区间,即遇到一个待更新区间的子区间
// 注意的是:
// 1.下沉这个标记的时候也要更新区间的实际和,下沉过的标记要及时取消
// 2.递归网上弹准备跳出的时候应该顺便更新区间的实际和,也就是把孩子的两个区间实际和相加
// 3.往左或者往右需要进行深层递归的条件:该区间的子区间与待更新区间存在交集
// 4.对我自己要说的,由于是先更新左区间,因此对右区间的更新不受影响,那么待更新的区间就不需要分割了
//

/*test data
1
10
4
1 5 2
5 9 3
1 1 1
10 10 1

out = 23
*/
#include <stdio.h>
#include <string.h>
#include <math.h>

const int M = 400001;
struct NODE{
int value;
int left,right; // 其实这两个区间端点都可以不用存起来
int buffer;	// 延时标记。
}node[M];

void BuildTree(int i,int left, int right){
node[i].left = left;
node[i].right = right;
node[i].value = node[i].right - node[i].left + 1;
node[i].buffer = 0;
if (node[i].left == node[i].right){
return ;
}
BuildTree(i<<1,left,(left+right)/2);
BuildTree((i<<1)+1,(left+right)/2+1,right);
}

int a,b,v; // updata interval = [a,b]
void UpdataTree(int i){ // only revise the buffer
if (a <= node[i].left && node[i].right <= b){ // if find a  interval contained goal interval completely
node[i].value = (node[i].right - node[i].left + 1 ) * v;
if (node[i].left != node[i].right) // 末结点不需要延时标记
node[i].buffer = v; // replace
return;
}
if (node[i].buffer){ // if exsit buffer
int l = i << 1;
node[l].buffer = node[l+1].buffer = node[i].buffer; // Make buffer sinking
node[i].buffer = 0;
node[l].value = (node[l].right - node[l].left + 1 ) * node[l].buffer; // 左孩子,利用buffer完成上一次未完成的更新
l++;
node[l].value = (node[l].right - node[l].left + 1 ) * node[l].buffer;	// 右孩子,利用buffer完成上一次未完成的更新
}
if (a <= node[i<<1].right) // ***由于先执行的左边,所以待更新区间无需分割,并不影响右边的执行****   ///
UpdataTree(i<<1);
if (b >= node[(i<<1)+1].left)
UpdataTree((i<<1)+1);
// finally, this node will be the sum of the two child
node[i].value = node[i<<1].value + node[(i<<1)+1].value;
}

int main(){
freopen("in.txt","r",stdin);
int ncase,d=1;
scanf("%d",&ncase);

while(ncase--){
int nn,n_u;
scanf("%d%d",&nn,&n_u);
BuildTree(1,1,nn);
while(n_u--){ // updata
scanf("%d%d%d",&a,&b,&v);
UpdataTree(1); // start from NO.1 interval to updata interval [1,nn] by increase v
}
printf("Case %d: The total value of the hook is %d.\n",d++,node[1].value);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: