区间更新需要用到延迟标记
即每次更新时,不需要更新到底,当搜索的区间在更新或者询问的区间内,就更新该区间并且加上延迟标记然后返回;
当下次更新或者询问时,先pushdown(按照延迟标记更新子树),然后再搜索左右子树(按照当前状态更新或者询问)
#include <cstdio>
using namespace std;
const int maxn = 100010;
int mark[maxn<<2];
int sumtr[maxn<<2];
void build(int l, int r, int rt);
void update(int L, int R, int x, int l, int r, int rt);
void pushup(int rt);
void pushdown(int rt, int len);
int main()
{
int t, n, m;
int cas;
scanf("%d", &t);
for(cas = 1; cas <= t; ++cas)
{
scanf("%d %d", &n, &m);
build(1, n, 1);
while(m--)
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
update(a, b, c, 1, n, 1);
}
printf("Case %d: The total value of the hook is %d.\n", cas, sumtr[1]);
}
return 0;
}
void pushdown(int rt, int len)
{
if(!mark[rt]) return;
mark[rt<<1] = mark[rt<<1|1] = mark[rt];
sumtr[rt<<1] = (len - (len>>1)) * mark[rt];
sumtr[rt<<1|1] = (len>>1) * mark[rt];
mark[rt] = 0;
}
void update(int L, int R, int x, int l, int r, int rt)
{
if(L <= l && r <= R)
{
mark[rt] = x;
sumtr[rt] = x * (r - l + 1);
return;
}
pushdown(rt, r - l + 1);
int mid = (l + r)>>1;
if(L <= mid)
update(L, R, x, l, mid, rt<<1);
if(R >= mid + 1)
update(L, R, x, mid + 1, r, rt<<1|1);
pushup(rt);
}
void pushup(int rt)
{
sumtr[rt] = sumtr[rt<<1] + sumtr[rt<<1|1];
}
void build(int l, int r, int rt)
{
mark[rt] = 0;
sumtr[rt] = 1;
if(l == r) return ;
int mid = (l + r)>>1;
build(l, mid, rt<<1);
build(mid + 1, r, rt<<1|1);
pushup(rt);
}