成段更新
需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候
这题算的是总价值,直接把根节点输出就好了
/* hdu 1698 该死的hook 延迟操作,进行标记,在下一次更新or查询时对上一次做了标记的进行更新, */ #include <cstdio> #include <iostream> using namespace std; #define MAX 300200 typedef struct node { int s,e; int mark; int value; node (int a = 0,int b= 0,int c =0,int d = 0):s(a),e(b),value(c),mark(d){} }node; node tree[MAX]; int n,q; void build (int T,int s,int e) { if (s == e) tree[T] = node (s,e,1,0); else { int mid = (s+e)>>1; build (T<<1,s,mid); build (T<<1|1,mid +1,e); tree[T] = node (s,e,(e-s+1),0); } } //孩子节点的标记 void change_down(int T,int p) { if (!p) return ; tree[T<<1].mark = p; tree[T<<1].value = (tree[T<<1].e-tree[T<<1].s+1)*p; tree[T<<1|1].mark = p; tree[T<<1|1].value = (tree[T<<1|1].e-tree[T<<1|1].s+1)*p; tree[T].mark = 0;//完成了向下传递就要消除标记 } //成段区间的更新 void update(int T,int x,int y,int p) { //找到包含的区间,直接更新 if (x<=tree[T].s && y>=tree[T].e) { tree[T].mark = p; tree[T].value = (tree[T].e-tree[T].s+1)*p; } else { //不包含,后面就会继续去子节点访问,那么前面标记过的节点的子节点未被标记 //而你会访问到,所以我们,先把标记过的节点的左右子节点标记上。 //标签向下传递,从而便可以计算出值,传回根节点,依次,算出总值 change_down(T,tree[T].mark); int mid = (tree[T].s + tree[T].e)>>1; if (x<=mid) update(T<<1,x,y,p); if (y>mid) update (T<<1|1,x,y,p); tree[T].value = tree[T<<1].value + tree[T<<1|1].value;//节点值更新 } } int main () { int T,t=1; scanf ("%d",&T); while(T--) { scanf ("%d%d",&n,&q); build (1,1,n); int x,y,op; for (int i=0;i<q;++i) { scanf ("%d%d%d",&x,&y,&op); update(1,x,y,op); } printf ("Case %d: The total value of the hook is %d.\n",t++,tree[1].value); } return 0; } /* 1 10 2 1 5 2 5 9 3 */