这道题如果第一次碰到这种类型的,大概会T,然后就要学习一种神奇的延迟标记的方法。通过这种标记在当前范围在有效查询区间内才将进行更新,这样可以避免一直更新到叶子结点,防止代码超时,膜ORZ。。。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<stack>//线段树区间更新,延迟标记
using namespace std;
typedef long long ll;
#define N 100010
int g[4*N];
int mk[4*N];//延迟标记,0表示没有标记,否则以更新的价值作为标记
void init(int rt, int l, int r)
{
mk[rt] = 0;
if(l == r)
{
g[rt] = 1;
return;
}
int mid = (l+r)>>1;
init(rt<<1, l, mid);
init(rt<<1|1, mid+1, r);
}
void PushUp(int rt)//向上更新
{
g[rt] = g[rt<<1]+g[rt<<1|1];
}
void PushDown(int rt, int m)//对某一个区间进行改变,如果被标记了,在查询的时候就得把改变传给子节点,因为查询的并不一定是当前区间
{
if(mk[rt])//已经被标记过,该区间被改变过
{
mk[rt<<1] = mk[rt<<1|1] = mk[rt];
g[rt<<1] = (m-(m>>1))*mk[rt];
g[rt<<1|1] = (m>>1)*mk[rt];
mk[rt] = 0;
}
}
void Update(int rt, int l, int r, int L, int R, int k)
{
if(l >= L && r <= R)
{
mk[rt] = k;
g[rt] = k*(r-l+1);
return;//mdzzORZ
//printf("l:%d r:%d g[rt]:%d\n", l, r, g[rt]);
}
PushDown(rt, r-l+1);//向下传递
int mid = (l+r)>>1;
if(mid >= L)
{
Update(rt<<1, l, mid, L, R, k);
}
if(mid < R)
{
Update(rt<<1|1, mid+1, r, L, R, k);
}
//printf("l:%d r:%d g[rt]:%d\n", l, r, k1+k2);
PushUp(rt);
}
int main()
{
int t, num = 0;
scanf("%d", &t);
while(t--)
{
int n, m;
scanf("%d%d", &n, &m);
init(1, 1, n);
while(m--)
{
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
Update(1, 1, n, l, r, k);
//PushUp(1, 1, n);
}
printf("Case %d: The total value of the hook is %d.\n", ++num, g[1]);
}
return 0;
}