来自大牛的分析:https://www.xuebuyuan.com/2967012.html
推荐:https://www.cnblogs.com/TenosDoIt/p/3453089.html#c
https://www.cnblogs.com/TheRoadToTheGold/p/6254255.html
区间更新,总区间求和
分析:
看到题目首先想到了线段树,(因为题目是区间更新)区间更新需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候。延迟标记的意思是:这个区间的左右儿子都需要被更新,但是当前区间已经更新了。
节点中存储的值代表这个区间的金属成色(1-铜,2-银,3-金;/如果这个区间还有其它成色,即杂色金属,则值为-1。
原创代码
#include<string>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 100000
int sum,n,m,x,y,z;
struct node{
int l,r,w;
}ac[maxn*4+1];//线段树占空间约为结点个数的 4 倍!
void build(int k,int l,int r)
{
ac[k].l=l;
ac[k].r=r;
ac[k].w=1;
if(l==r){
return ;
}
int mid=(ac[k].l+ac[k].r)/2;
build(k*2,l,mid);
build(k*2+1,mid+1,r);
}
//区间更新
void up(int k,int l,int r,int v)
{
if(ac[k].l==l && ac[k].r==r)
{
ac[k].w=v;
return ;
}
if(ac[k].w==v)
return ;
if(ac[k].w!=-1)//编号为k的区间都为纯色
{ //下面附上颜色值
ac[2*k].w=ac[2*k+1].w=ac[k].w;
ac[k].w=-1;
}
int mid=(ac[k].l+ac[k].r)/2;
if(mid>=r)
{
up(k*2,l,r,v);
}
else if(mid<l)
{
up(k*2+1,l,r,v);
}
else{
up(k*2,l,mid,v);
up(k*2+1,mid+1,r,v);
}
}
int query(int k,int l,int r){
if(ac[k].w==-1) return query(k*2,l,r)+query(k*2+1,l,r);
else return (ac[k].r-ac[k].l+1)*ac[k].w;//编号k都是纯色
}
int main(){
while(scanf("%d",&sum)!=EOF){
for(int s=1;s<=sum;s++){
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
up(1,x,y,z);
}
printf("Case %d: The total value of the hook is %d.\n",s,query(1,1,n));
}
}
return 0;
}