HDU 1698 Just a Hook(线段树区间更新)


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698

       题意是一共有金银铜三种钩子,铜钩子的价值是1,银钩子是2,金钩子是3,刚开始都是铜钩子。首先输入一个数T,表示有T组数据,然后输入钩子的个数n,代表编号为从1到n,然后再输入一个数m表示有m组操作,然后每组操作有a,b,c三个数表示编号从a到b的钩子都更改为价值为c的钩子,最后输出这n个钩子的总价值。

      这个就是线段树的区间更新问题,比单点更新多了个Pushdown的操作和add数组来进行标记,首先进行初始化,使pre数组都为1,add数组都为0,当查找的范围在当前结点的范围内的话,就更新当前结点的值(ans乘上这个结点的范围),然后把当前结点的add数组标记一下,表明这个结点往后的子结点都没有更新过,然后进行一下Pushdown操作(向下更新,看代码应该能看懂),最后问总价值,就直接输出第一个结点就好了。


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define lson l, mid, o << 1
#define rson mid + 1, r, o << 1 | 1
#define maxn 100005
using namespace std;
int T,n,m;
int pre[maxn << 2],add[maxn << 2];

void Pushup(int o){
  pre[o] = pre[o << 1] + pre[o << 1 | 1];
}

void Pushdown(int o, int ans){
  if(add[o]){
    add[o << 1] = add[o];     // 向下更新
    add[o << 1 | 1] = add[o];
    pre[o << 1] = add[o] * (ans - (ans >> 1));   // 赋值
    pre[o << 1 | 1] = add[o] * (ans >> 1);
    add[o] = 0;               // 清零
  }
}

void Build(int l,int r,int o){
  pre[o] = 1;
  add[o] = 0;
  if(l == r)return ;
  int mid = (l + r) >> 1;
  Build(lson);
  Build(rson);
  Pushup(o);
}

void Update(int L,int R,int ans,int l,int r,int o){
  if(L <= l && r <= R){
    pre[o] = ans * (r - l + 1);         // 价值乘上长度
    add[o] = ans;                       // 标记
    return ;
  }
  Pushdown(o, r - l + 1);
  int mid = (l + r) >> 1;
  if(L <= mid)Update(L,R,ans,lson);
  if(R > mid)Update(L,R,ans,rson);
  Pushup(o);
}

int main()
{
  int Case = 1;
  scanf("%d",&T);
  while(T--){
    scanf("%d",&n);
    Build(1,n,1);
    scanf("%d",&m);
    while(m--){
      int x,y,z;
      scanf("%d%d%d",&x,&y,&z);
      Update(x,y,z,1,n,1);
    }
    printf("Case %d: The total value of the hook is %d.\n",Case++,pre[1]);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/charles_zaqdt/article/details/81061473