题目链接: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;
}