#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int MAXN=100010;
typedef long long LL;
int lazy[3*MAXN]; //懒惰标记数组
int num[MAXN];
struct Node
{
int l,r;
LL nSum;
}segTree[MAXN*3];
void pushdown(int root,int len) //len为变动区间长度
{
if(lazy[root]) {
lazy[root<<1]=lazy[root]; //更新原值
lazy[(root<<1)+1]=lazy[root];
segTree[root<<1].nSum=(LL)(lazy[root]*(len-(len>>1))); //更新sum值
segTree[(root<<1)+1].nSum=(LL)(lazy[root]*(len>>1)); //以上两个式子不可改变
lazy[root]=0;
}
}
void Build(LL i,LL l,LL r) //1 1 n
{
segTree[i].l=l;
segTree[i].r=r;
if(l==r)
{
segTree[i].nSum=num[l];
return;
}
LL mid=(l+r)>>1; //右移运算符,除以2的n次
Build(i<<1,l,mid); //左移运算符,乘以2的n次
Build((i<<1)+1,mid+1,r);
segTree[i].nSum=(LL)(segTree[i<<1].nSum+segTree[(i<<1)+1].nSum); //父节点的值为两子节点之和
}
void pushup(int root)
{
segTree[root].nSum=(LL)(segTree[root<<1].nSum+segTree[(root<<1)+1].nSum);
}
//未完成由下向上的更新
void Add(int i,int t,LL b,int val) //由上至下到达查找点,由下向上的更新,t b为区间,val为变动值
{
/*segTree[i].nSum+=b;
if(segTree[i].l==t&&segTree[i].r==t) return; //不更新叶节点
LL mid=(segTree[i].l+segTree[i].r)>>1;
if(t<=mid) Add(i<<1,t,b); //判断左右节点
else Add((i<<1)+1,t,b);*/
if(t==segTree[i].l&&b==segTree[i].r) { //到达区间根节点
lazy[i]=val;
segTree[i].nSum=(LL) ((b-t+1)*val);
return;
}
if(segTree[i].l==segTree[i].r) return; //到达叶节点,未进行更新
int mid=(segTree[i].l+segTree[i].r)>>1;
pushdown(i,segTree[i].r-segTree[i].l+1); //向下更新lazy标记
if(t>mid) Add((i<<1)+1,t,b,val); //搜寻右子树
else if(b<=mid) Add(i<<1,t,b,val); //搜寻左子树
else { //区间在mid两边
Add(i<<1,t,mid,val);
Add((i<<1)+1,mid+1,b,val);
}
pushup(i);
}
//查询
/*LL Query(LL i,LL l,LL r)
{
if(l==segTree[i].l&&r==segTree[i].r) //左右区间正好符合
return segTree[i].nSum;
pushdown(i, segTree[i].r - segTree[i].l + 1); //如果查询区间小于标记区间,则需要继续向下标记
LL mid=(segTree[i].l+segTree[i].r)>>1; //寻找中值
if(r<=mid) return Query(i<<1,l,r); //区间在中值左侧
else if(l>mid) return Query((i<<1)+1,l,r); //区间在中值右侧
else return Query(i<<1,l,mid)+Query((i<<1)+1,mid+1,r); //区间在中值两侧分布
}*/
int main()
{
int t,kase=0;
scanf("%d",&t);
while(t--)
{
memset(lazy,0,sizeof(lazy));
int n,q; //n为个数,q为操作数
scanf("%d",&n);
scanf("%d",&q);
for(int i=1;i<=n;i++)
num[i]=1;
//memset(num,0,sizeof(num));
Build(1,1,n);
while(q--)
{
int x,y,z; //x y为操作区间,z为改变类型
scanf("%d%d%d",&x,&y,&z);
Add(1,x,y,z);
}
LL sum=segTree[1].nSum;
printf("Case %d: The total value of the hook is ",++kase);
cout<<sum<<"."<<endl;
}
return 0;
}
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int MAXN=100010;
typedef long long LL;
int lazy[3*MAXN]; //懒惰标记数组
int num[MAXN];
struct Node
{
int l,r;
LL nSum;
}segTree[MAXN*3];
void pushdown(int root,int len) //len为变动区间长度
{
if(lazy[root]) {
lazy[root<<1]=lazy[root]; //更新原值
lazy[(root<<1)+1]=lazy[root];
segTree[root<<1].nSum=(LL)(lazy[root]*(len-(len>>1))); //更新sum值
segTree[(root<<1)+1].nSum=(LL)(lazy[root]*(len>>1)); //以上两个式子不可改变
lazy[root]=0;
}
}
void Build(LL i,LL l,LL r) //1 1 n
{
segTree[i].l=l;
segTree[i].r=r;
if(l==r)
{
segTree[i].nSum=num[l];
return;
}
LL mid=(l+r)>>1; //右移运算符,除以2的n次
Build(i<<1,l,mid); //左移运算符,乘以2的n次
Build((i<<1)+1,mid+1,r);
segTree[i].nSum=(LL)(segTree[i<<1].nSum+segTree[(i<<1)+1].nSum); //父节点的值为两子节点之和
}
void pushup(int root)
{
segTree[root].nSum=(LL)(segTree[root<<1].nSum+segTree[(root<<1)+1].nSum);
}
//未完成由下向上的更新
void Add(int i,int t,LL b,int val) //由上至下到达查找点,由下向上的更新,t b为区间,val为变动值
{
/*segTree[i].nSum+=b;
if(segTree[i].l==t&&segTree[i].r==t) return; //不更新叶节点
LL mid=(segTree[i].l+segTree[i].r)>>1;
if(t<=mid) Add(i<<1,t,b); //判断左右节点
else Add((i<<1)+1,t,b);*/
if(t==segTree[i].l&&b==segTree[i].r) { //到达区间根节点
lazy[i]=val;
segTree[i].nSum=(LL) ((b-t+1)*val);
return;
}
if(segTree[i].l==segTree[i].r) return; //到达叶节点,未进行更新
int mid=(segTree[i].l+segTree[i].r)>>1;
pushdown(i,segTree[i].r-segTree[i].l+1); //向下更新lazy标记
if(t>mid) Add((i<<1)+1,t,b,val); //搜寻右子树
else if(b<=mid) Add(i<<1,t,b,val); //搜寻左子树
else { //区间在mid两边
Add(i<<1,t,mid,val);
Add((i<<1)+1,mid+1,b,val);
}
pushup(i);
}
//查询
/*LL Query(LL i,LL l,LL r)
{
if(l==segTree[i].l&&r==segTree[i].r) //左右区间正好符合
return segTree[i].nSum;
pushdown(i, segTree[i].r - segTree[i].l + 1); //如果查询区间小于标记区间,则需要继续向下标记
LL mid=(segTree[i].l+segTree[i].r)>>1; //寻找中值
if(r<=mid) return Query(i<<1,l,r); //区间在中值左侧
else if(l>mid) return Query((i<<1)+1,l,r); //区间在中值右侧
else return Query(i<<1,l,mid)+Query((i<<1)+1,mid+1,r); //区间在中值两侧分布
}*/
int main()
{
int t,kase=0;
scanf("%d",&t);
while(t--)
{
memset(lazy,0,sizeof(lazy));
int n,q; //n为个数,q为操作数
scanf("%d",&n);
scanf("%d",&q);
for(int i=1;i<=n;i++)
num[i]=1;
//memset(num,0,sizeof(num));
Build(1,1,n);
while(q--)
{
int x,y,z; //x y为操作区间,z为改变类型
scanf("%d%d%d",&x,&y,&z);
Add(1,x,y,z);
}
LL sum=segTree[1].nSum;
printf("Case %d: The total value of the hook is ",++kase);
cout<<sum<<"."<<endl;
}
return 0;
}