http://acm.hdu.edu.cn/showproblem.php?pid=1698
大意:给一组棍子染色,不同的颜色有不同的值,执行一系列的区间染色后,问这组棍子的总值是多少。
题目分析:建树:节点的域有左右节点和颜色,l,r,num;num=0时表示这个区间由多种颜色覆盖。
更新的时候,如果更新区间比当前区间小,并且当前区间的颜色大于0,说明已经被完全染色,就把该区间颜色传递到左右子树上,该区间染色为0,然后根据更新区间的大小,在左右子树上去搜索。
求和的时候遇到区间的num>0的时候说明完全被染色过了,就把区间的长度乘以颜色的值加到总和里面去,然后结束这个方向的递归查询,
代码:
#include<iostream>
using namespace std;
struct node
{
int l,r,num;
}tree[400000];
int ans;
void build(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
tree[i].num=1;
if(l==r)
return;
else
{
int mid=(l+r)/2;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
}
}
void updata(int i,int l,int r,int v)
{
if(l==tree[i].l&&r==tree[i].r)
{
tree[i].num=v;
return;
}
if(tree[i].num==v)
return ;
if(tree[i].num>0)
{
tree[i*2+1].num=tree[i*2].num=tree[i].num;
tree[i].num=0;
}
int mid=(tree[i].l+tree[i].r)/2;
if(r<=mid)
{
updata(i*2,l,r,v);
}
else
if(l>mid)
updata(i*2+1,l,r,v);
else
{
updata(i*2,l,mid,v);
updata(i*2+1,mid+1,r,v);
}
}
void getsum(int i,int l,int r)
{
if(tree[i].num>0)
{
ans+=(tree[i].r-tree[i].l+1)*tree[i].num; //注意,要加1
return ;
}
else
{
int mid=(tree[i].l+tree[i].r)/2;
if(r<=mid)
getsum(i*2,l,r);
else
if(l>mid)
getsum(i*2+1,l,r);
else
{
getsum(i*2,l,mid);
getsum(i*2+1,mid+1,r);
}
}
}
int main()
{
int t,k=0;;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int m;
scanf("%d",&m);
build(1,1,n);
while(m--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
updata(1,x,y,z);
}
ans=0;
getsum(1,1,n);
printf("Case %d: The total value of the hook is %d.\n",++k,ans);
}
return 0;
}