题意:
给一组棍子染色,不同的颜色有不同的值,执行一系列的区间染色后,问这组棍子的总值是多少。初始值都是1。
线段树的成段更新,和基本的线段树的差别就是加了一个lazy标记,记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加
了线段树的效率。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698
#include<stdio.h>
#include<string.h>
struct node
{
int r,l;
int num;
}stu[400000];
void build(int x,int y,int n)
{
int mid;
stu[n].l=x;
stu[n].r=y;
stu[n].num=1;
if(x==y)
return ;
mid=(x+y)/2;
build(x,mid,n*2);
build(mid+1,y,n*2+1);
}
void down(int l,int r,int x,int k)
{
if(stu[x].l==l&&stu[x].r==r) //更新到满足条件的结点,不继续向下更新
{
stu[x].num=k;
return ;
}
/***************/
if(stu[x].num!=-1) //核心思想,每次查询到结点时才往下更新,节省时间
{
stu[2*x].num=stu[x].num;
stu[2*x+1].num=stu[x].num;
stu[x].num=-1;
}
/***************/
if(l>=stu[x*2+1].l)
down(l,r,2*x+1,k);
else if(r<=stu[x*2].r)
down(l,r,2*x,k);
else
{
down(l,stu[2*x].r,2*x,k);
down(stu[2*x+1].l,r,2*x+1,k);
}
}
int end(int x)
{
if(stu[x].num>0)
return (stu[x].r-stu[x].l+1)*stu[x].num;
return end(2*x)+end(2*x+1);
}
int main()
{
int t,n,i,j,k,sum,a,b,c,f=0;
scanf("%d",&t);
while(t--)
{
f++;
sum=0;
scanf("%d",&n);
build(1,n,1);
scanf("%d",&k);
while(k--)
{
scanf("%d%d%d",&a,&b,&c);
down(a,b,1,c);
}
printf("Case %d: The total value of the hook is %d.\n",f,end(1));
}
return 0;
}