hdu 1698

成段更新

需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新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
*/

 

posted @ 2017-12-16 21:46  雨落洛  阅读(181)  评论(0编辑  收藏  举报