题意 :
大致是说有三种钩子,铜金银,分别有不同的价值,钩子有不同的覆盖范围,可以切换钩子的状态,问最后钩子的总值是多少
这题转化一下就是问更新某一区间的值,求该区间的总和,也就是线段树的成段更新。
代码:
#include <cstdio>
#include <cstring>
using namespace std;
int sum[100000 << 2];
int v[100000 << 2];
void pushup(int rt)
{
sum[rt] = sum[rt << 1] + sum[rt << 1|1];
}
void pushdown(int rt, int m) //延迟函数,这是线段树成段更新的核心
{
if(v[rt])
{
v[rt << 1] = v[rt << 1|1] = v[rt];
sum[rt << 1] = (m -(m >> 1)) * v[rt];
sum[rt << 1|1] = (m >> 1) * v[rt];
v[rt] = 0;
}
}
void build(int l, int r, int rt)
{
if(l == r)
{
sum[rt] = 1;
v[rt] = 0;
return;
}
int mid = (l + r) >> 1;
build(l, mid , rt << 1);
build(mid + 1, r, rt << 1|1);
pushup(rt);
}
void update(int L, int R, int c, int l, int r, int rt)
{
if(L<= l && R>= r) //其实和单点更新是一样的,这里把区间看成一个点即可
{
v[rt] = c;
sum[rt] = c * (r - l + 1);
return;
}
pushdown(rt, r - l + 1);//更新并标记
int mid = (l + r) >> 1;
if(L <= mid) update(L, R, c, l, mid, rt << 1);
if(R > mid) update(L, R, c, mid + 1, r, rt << 1|1);
pushup(rt);
}
int query(int L, int R, int l, int r, int rt)
{
if(L <= l && R >= r)
{
return(sum[rt]);
}
pushdown(rt, r - l + 1);//先更新
int mid = (l + r) >> 1;
if(L <= mid) query(L, R, l, mid, rt << 1);
if(R > mid) query(L, R, mid + 1, r, rt << 1|1);
}
int main()
{
int T;
scanf("%d",&T);
for(int i=1; i <= T; i++)
{
int n,m;
scanf("%d",&n);
scanf("%d",&m);
build(1,n,1);
//for(int j = 1; j <= 40; j++)
// printf("%d ",sum[j]);
memset(v,0,sizeof(v));
while(m --)
{
int a,b,c;
scanf("%d %d %d",&a, &b, &c);
update(a,b,c,1,n,1);
//printf("%d\n",m);
}
printf("Case %d: The total value of the hook is %d.\n",i, query(1,n,1,n,1));
}
return 0;
}