线段树,继续刷。这个题目是poj2777的简单版本。poj 2777是区间涂色问题。给出的颜色不超过30中,每一个值代表一种颜色。但是这个题目给定的三个环,每个环都有一个固定的权值。处理方法是一样的。非叶子节点所在地区间。如果环不止一种的话,就可以用-1来标记。如果是一种的话,就用一个代表环的值来标记。这样更新和计数的时候都比较方便,节省大量的时间,没必要到叶子节点。
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 120000
struct SegTree
{
int l,r,mid;
int num;
}tree[N*3];
void BulidTree(int root,int l,int r)
{
tree[root].num=1;
tree[root].l=l;
tree[root].r=r;
tree[root].mid=(l+r)/2;
if(l==r)return;
BulidTree(2*root,l,tree[root].mid);
BulidTree(2*root+1,tree[root].mid+1,r);
}
void Updata(int root,int l,int r,int c)
{
if(tree[root].num==c)return;
if(tree[root].l==l&&tree[root].r==r) //这两个结合起来使用,保证这段是完全更新的
{
tree[root].num=c;
return ;
}
if(tree[root].num!=-1) //想一想,两个if结合起来使用,有什么用途了
{ //如果下次更新的时候,区间是这个区间的一个部分,那么这个if就起作用了
tree[2*root].num=tree[root].num;
tree[2*root+1].num=tree[root].num;
tree[root].num=-1;
}
if(r<=tree[root].mid)
{
Updata(2*root,l,r,c);
}
else if(l>tree[root].mid)
{
Updata(2*root+1,l,r,c);
}
else
{
Updata(2*root,l,tree[root].mid,c);
Updata(2*root+1,tree[root].mid+1,r,c);
}
}
int count(int root)
{
if(tree[root].num>0)
{
return (tree[root].r-tree[root].l+1)*tree[root].num;
}
return count(2*root)+count(2*root+1);
}
int main()
{
int t,cn=0;
scanf("%d",&t);
while(t--)
{
int n,oper;
scanf("%d%d",&n,&oper);
BulidTree(1,1,n);
while(oper--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
Updata(1,a,b,c);
}
printf("Case %d: The total value of the hook is %d.\n",++cn,count(1));
}
return 0;
}