/***********************************************
Copyright:Glder
Author:Glder
Date:2013-08-03 14:54:46
Destription:
1、插线问题(成段更新)
2、建树结构体中是需要多加个元素权值
3、建树操作中注意
A:
if(l == r)
{
s[root].num = 1;
s[root].x = 0;
cout<<"root: "<<root<<endl;
return;
}
如果这样写,不能把所有s[root].x都更新一遍,出现wa;
只需把s[root].x = 0;提到if语句外面即可ac,因为最后
有个pushup语句可以保证能把每个num都更新到。
B:
s[root].num = 1;
s[root].x = 0;
cout<<"root: "<<root<<endl;
if(l == r)
{
return;
}
如果这样写,建树顺序如下:
root:1 2 4 8 16 17 9 5 10 11 3 6 12 24 25 13 7 14 15
4、注意更新操作中要有注意更新时需要从父节点到子节点,
这是此题要重点理解的内容。
5、本题最后需要查询全部值的和,可以直接输出s[1].num,
也可以直接使用query(1,1,n);
***********************************************/
#include<iostream>
#include<cstdio>
using namespace std;
struct Segtree
{
int left;
int right;
int num;
int x;//权值
}s[100005<<2];
void build(int root,int l,int r)
{
s[root].left = l;
s[root].right = r;
s[root].x = 0;
if(l == r)
{
s[root].num = 1;
return;
}
int m = (l+r)/2;
build(root<<1,l,m);
build(root<<1|1,m+1,r);
s[root].num = s[root<<1].num + s[root<<1|1].num;
}
void update(int root,int a,int b,int x)
{
int l = s[root].left;
int r = s[root].right;
if(a <= l && b >= r)
{
s[root].num = x*(r-l+1);
s[root].x = x;
return;
}
if(s[root].x)//把当前节点信息更新到叶子节点
{
int p = r - l + 1;
s[root<<1].x = s[root].x;
s[root<<1|1].x = s[root].x;
s[root<<1].num = (p - p/2)*s[root].x;
s[root<<1|1].num = (p/2)*s[root].x;
s[root].x = 0;
}
int m = (l + r)>>1;
if(a <= m)
update(root<<1,a,b,x);
if(b > m)
update(root<<1|1,a,b,x);
s[root].num = s[root<<1].num + s[root<<1|1].num;
}
int query(int root,int a,int b)
{
int l = s[root].left;
int r = s[root].right;
if(a == l && b == r)
return s[root].num;
int m = (l + r) >> 1;
int cnt = 0;
if(a <= m)
cnt += query(root<<1,a,b);
if(b > m)
cnt += query(root<<1|1,a,b);
return cnt;
}
int main()
{
int t,n,q;
int x,y,c;
scanf("%d",&t);
int cas = 1;
while(t--)
{
scanf("%d",&n);
build(1,1,n);
scanf("%d",&q);
while(q--)
{
scanf("%d%d%d",&x,&y,&c);
update(1,x,y,c);
}
printf("Case %d: The total value of the hook is %d.\n",cas++,query(1,1,n));
}
}