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

来源:互联网 发布:在windows资源管理器 编辑:程序博客网 时间:2024/04/29 04:52
// HDU 1698 Just a Hook 线段树(线段替换)插线插线+ 延时标记// 延时标记:起一个缓冲的作用,第一次遇到的更新先不更新到底,等下一次更新或者查询的时候再更新到位。// 因此线段树结构中的区间和 并不是实际值。// 此处的更新到位是指 本次更新或查询所需的最后一层(因为我查的不是点,而是区间),并非到最底层// 延时标记下沉的前提:线段树结构中遇到了一个区间完全的包含于待更新区间,即遇到一个待更新区间的子区间// 注意的是:// 1.下沉这个标记的时候也要更新区间的实际和,下沉过的标记要及时取消// 2.递归网上弹准备跳出的时候应该顺便更新区间的实际和,也就是把孩子的两个区间实际和相加// 3.往左或者往右需要进行深层递归的条件:该区间的子区间与待更新区间存在交集// 4.对我自己要说的,由于是先更新左区间,因此对右区间的更新不受影响,那么待更新的区间就不需要分割了// /*test data11041 5 25 9 31 1 110 10 1out = 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 completelynode[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 sinkingnode[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--){ // updatascanf("%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;}

原创粉丝点击