题目大意:DOTA中屠夫的钩子有N个链子组成,每个链子可有金,银,铜,三种材质做成,铜链价值1,银价值2,金价值3,先对钩子进行Q次的更新操作,求出更新完后钩子的价值。
算法思想:
主要使用线段数的区间成段更新操作,首先间一个规模为N的线段树,然后用一个标记数组记录线段树每个节点的价值,之后在此基础上按照对钩子的更新操作进行线段树的更新,最后统计出钩子的价值。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=111111;
int Sum[MAXN<<2];
int Col[MAXN<<2];//延迟标记
void PushUp(int rt){
Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];
}
void PushDown(int rt,int m){//m为更新区间的大小
if(Col[rt]){
Col[rt<<1]=Col[rt<<1|1]=Col[rt];//使根节点与孩子节点的标记一致
Sum[rt<<1]=(m-(m>>1))*Col[rt];//左孩子节点的价值
Sum[rt<<1|1]=(m>>1)*Col[rt];//右孩子节点的价值
Col[rt]=0;
}
}
void Build(int l,int r,int rt){
Col[rt]=0;
Sum[rt]=1;
if(l==r) return ;
int m=(l+r)>>1;
Build(lson);
Build(rson);
PushUp(rt);
}
void Update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){//更新区间包含了整个区间
Col[rt]=c;
Sum[rt]=c*(r-l+1);
return ;
}
PushDown(rt,r-l+1);
int m=(l+r)>>1;
if(L<=m) Update(L,R,c,lson);//左子树
if(R>m) Update(L,R,c,rson);//右子树
PushUp(rt);
}
int main(){
int T,N,Q;
cin>>T;
for(int i=1;i<=T;i++){
cin>>N>>Q;
Build(1,N,1);
while(Q--){
int x,y,z;
cin>>x>>y>>z;
Update(x,y,z,1,N,1);
}
cout<<"Case "<<i<<": The total value of the hook is "<<Sum[1]<<"."<<endl;
}
return 0;
}