题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698
题目大意:有一个长度为n(100000)的钩子,没个单位长度的钩子有金,银,铜三者之一构成,价值分别为3,2,1,现在进行Q(100000)次操作,每次操作表示把一个区间[l,r]内的钩子变成一种颜色,问Q次操作之后钩子的总价值。
分析:我们用线段树来纪录每一个区间内的颜色,更新到区间为止。
实现代码如下:
#include <cstdio>
using namespace std;
const int maxn=1000005;
struct segment
{
int l,r;
int mid()
{
return (l+r)>>1;
}
int ins; //纪录区间的改变值
}tree[maxn<<2];
void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
tree[root].ins=1;
if(l==r) return ;
int mid=tree[root].mid();
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
}
void update(int root,int l,int r,int v)
{
if(tree[root].ins==v) return ;
if(tree[root].l==l&&tree[root].r==r)
{
tree[root].ins=v;
return ;
}
if(tree[root].ins!=-1)
{//该区间只有一种颜色,更新子树的权值等于父节点的权值
tree[root<<1].ins=tree[root].ins;
tree[root<<1|1].ins=tree[root].ins;
tree[root].ins=-1;//标记该区间为杂色
}
//父节点为杂色时对所有子节点进行更新
int mid=tree[root].mid();
if(r<=mid) update(root<<1,l,r,v);
else if(l>mid) update(root<<1|1,l,r,v);
else
{
update(root<<1,l,mid,v);
update(root<<1|1,mid+1,r,v);
}
}
int query(int root)
{
if(tree[root].ins!=-1)
return (tree[root].r-tree[root].l+1)*tree[root].ins;
else return query(root<<1)+query(root<<1|1);
}
int main()
{
int n,q,t,T=1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
build(1,1,n);
while(q--)
{
int l,r,v;
scanf("%d%d%d",&l,&r,&v);
update(1,l,r,v);
}
printf("Case %d: The total value of the hook is %d.\n",T++,query(1));
}
return 0;
}