Just a Hook
In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of the same length.

Now Pudge wants to do some operations on the hook.
Let us number the consecutive metallic sticks of the hook from 1 to N. For each operation, Pudge can change the consecutive metallic sticks, numbered from X to Y, into cupreous sticks, silver sticks or golden sticks.
The total value of the hook is calculated as the sum of values of N metallic sticks. More precisely, the value for each kind of stick is calculated as follows:
For each cupreous stick, the value is 1.
For each silver stick, the value is 2.
For each golden stick, the value is 3.
Pudge wants to know the total value of the hook after performing the operations.
You may consider the original hook is made up of cupreous sticks.
Now Pudge wants to do some operations on the hook.
Let us number the consecutive metallic sticks of the hook from 1 to N. For each operation, Pudge can change the consecutive metallic sticks, numbered from X to Y, into cupreous sticks, silver sticks or golden sticks.
The total value of the hook is calculated as the sum of values of N metallic sticks. More precisely, the value for each kind of stick is calculated as follows:
For each cupreous stick, the value is 1.
For each silver stick, the value is 2.
For each golden stick, the value is 3.
Pudge wants to know the total value of the hook after performing the operations.
You may consider the original hook is made up of cupreous sticks.
For each case, the first line contains an integer N, 1<=N<=100,000, which is the number of the sticks of Pudge’s meat hook and the second line contains an integer Q, 0<=Q<=100,000, which is the number of the operations.
Next Q lines, each line contains three integers X, Y, 1<=X<=Y<=N, Z, 1<=Z<=3, which defines an operation: change the sticks numbered from X to Y into the metal kind Z, where Z=1 represents the cupreous kind, Z=2 represents the silver kind and Z=3 represents the golden kind.
1
10
2
1 5 2
5 9 3
Case 1: The total value of the hook is 24.
code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 100100;
int num,n,q;
int tre[maxn<<2],lazy[maxn<<2];//线段树的数组,懒惰标记数组,开大于四倍(据说是因为经验所以开四倍)
//创建线段树
void Build(int l,int r,int rt){
if(l==r){//如果l==r到了叶子,直接赋值
tre[rt] = 1;//题目要求初始为1
return;
}
int mid = l+r>>1;//取中点值
Build(lson);
Build(rson);//递归左右建树
tre[rt] = tre[rt<<1]+tre[rt<<1|1];//回溯过程中给父节点返回子节点的信息
}
//懒惰标记的向下调整
void pushDown(int l,int r,int rt){
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];//把懒惰标记传给原来节点的两个儿子
int mid = l+r>>1;//划分出左右儿子
tre[rt<<1] = (mid-l+1)*lazy[rt];
tre[rt<<1|1] = (r-mid)*lazy[rt];//更新儿子的值
lazy[rt] = 0;//更新结束原来那个点的懒惰标记可以消失了
}
//对线段树进行更新,这里是求一段的和
void Update(int x,int y,int z,int l,int r,int rt){
if(x<=l&&y>=r){
tre[rt] = (r-l+1)*z;//更新这一区间的信息
lazy[rt] = z;//并把这个点进行懒惰标记,不继续向下更新
return ;
}
if(lazy[rt])pushDown(l,r,rt);//如果需要继续向下寻找,则如果懒惰标记存在,就要向下更新
int mid = l+r>>1;
if(x<=mid)Update(x,y,z,lson);//如果左子树中有要查找的,就要遍历左树
if(y>mid)Update(x,y,z,rson);//同理如果右子树中含有要查找的,就要遍历右树
tre[rt] = tre[rt<<1]+tre[rt<<1|1];//更新完后回溯返回给父节点信息
}
int main(){
int i;
int cases = 0;
scanf("%d",&num);
while(num--){
memset(tre,0,sizeof(tre));
memset(lazy,0,sizeof(lazy));//先初始化
scanf("%d",&n);
Build(1,n,1);//建树
scanf("%d",&q);
int x,y,z;
while(q--){
scanf("%d%d%d",&x,&y,&z);
Update(x,y,z,1,n,1);
}
printf("Case %d: The total value of the hook is %d.\n",++cases,tre[1]);
}
return 0;
}