点击打开链接hdu1698
思路:线段树成段更新
分析:
1 成段更新和单点更新是不同的,单点更新是要更新到叶子节点,但是对于成段更新是更新到某个区间即可,找个区间是当前需要的更新的区间的最大的子区间
2 成段更新需要维护一个“延时标记”,初始化看情况。我们先把标记放在一个大的区间,下次遇到的时候再进行向下的更新(标记传递)
3 建好线段树然后更新,最后输出节点1的和即可
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 100010; struct Node{ int left; int right; int mark; int sum; }; Node node[4*MAXN]; int N , Q; //向上更新 void push_up(int pos){ node[pos].sum = node[pos<<1].sum + node[(pos<<1)+1].sum; } //向下更新 void push_down(int pos){ if(node[pos].mark){ node[pos<<1].mark = node[pos].mark; node[(pos<<1)+1].mark = node[pos].mark; node[pos<<1].sum = node[pos<<1].mark*(node[pos<<1].right-node[pos<<1].left+1); node[(pos<<1)+1].sum = node[(pos<<1)+1].mark*(node[(pos<<1)+1].right-node[(pos<<1)+1].left+1); node[pos].mark = 0; } } //建立线段树 void buildTree(int left , int right , int pos){ node[pos].left = left; node[pos].right = right; node[pos].mark = 1; if(left == right){ node[pos].sum = 0; return; } int mid = (left+right)>>1; buildTree(left , mid , pos<<1); buildTree(mid+1 , right , (pos<<1)+1); push_up(pos); } //更新 void update(int left , int right , int value , int pos){ if(left <= node[pos].left && right >= node[pos].right){ node[pos].mark = value; node[pos].sum = value*(node[pos].right-node[pos].left+1); return; } push_down(pos);//向下更新 int mid = (node[pos].left + node[pos].right)>>1; if(right <= mid) update(left , right , value , pos<<1); else if(left > mid) update(left , right , value , (pos<<1)+1); else{ update(left , mid , value , pos<<1); update(mid+1 , right , value , (pos<<1)+1); } push_up(pos);//向上更新 } int main(){ int tmp = 1; int Case , cntCase = 1; int x , y , value; scanf("%d" , &Case); while(Case--){ scanf("%d%d" , &N , &Q); buildTree(1 , N , 1); while(Q--){ scanf("%d%d%d" , &x , &y , &value); update(x , y , value , 1); } printf("Case %d: The total value of the hook is %d.\n" , cntCase++ , node[1].sum); } return 0; }