又是一道线段树的题目,题目大意就是给你线段[a, b]和一个价值c,那么[a, b]这条线段的值就是c,现在求整个线段的价值。因为每条线段的价值可能会被后面更小的区间价值覆盖,所以这就是很明显的线段树。
一开始以为这题很水,因为只需要把每一个单位长度的线段值累加直到求出[1, tot]的值就可以了,但是写完之后提交发现超时,后来发现[a, b]之间线段值是一样的,那么只需要求出每一个线段值对应的线段长度然后相乘就可以了。
那么标记所有的混合线段的cover=-1,现在插入一条线段,如果当前被插入的线段值不等于-1且颜色和要插入的线段颜色不同就说明这个被插入线段的区间要变成混合色,不停地重复下去直到数据输入完毕。
到最后我们就会得到全部纯色线段的区间,只需要用递归求出每一段纯色线段区间的长度乘以相应的cover值就可以了。
#include <iostream>
using namespace std;
const int size = 100010;
struct STree
{
int l, r;
int cover;
}stree[3*size];
void creat(int num, int l, int r)
{
stree[num].l = l, stree[num].r = r, stree[num].cover = 1;
if (l == r)return ;
int mid = (l+r) >> 1;
int p = num << 1;
creat(p, l, mid);
creat(p+1, mid+1, r);
//stree[num].cover = stree[p].cover + stree[p+1].cover;
}
void insert(int num, int l, int r, int c)
{
int a = stree[num].l, b = stree[num].r;
int mid = (a+b)>> 1;
int p = num << 1;
if (stree[num].cover == c)return ;//如果当前线段颜色就是之前已经涂上的颜色
if (a == l && r== b ){//把a~b之间先涂成纯色
stree[num].cover = c;
return ;
}
if (stree[num].cover != -1){//如果当前线段为纯色,而又要插入另一颜色的线段,则将其孩子都保存为之前的颜色,然后将父线段保存为混合色-1
stree[p].cover = stree[p+1].cover = stree[num].cover;
stree[num].cover = -1;
}
if (r <= mid)insert(p, l, r, c);
else
if (l > mid)insert(p+1, l, r, c);
else {
insert(p, l, mid, c);
insert(p+1, mid+1, r, c);
}
//stree[num].cover = stree[p].cover + stree[p+1].cover;
}
int counter(int num)
{
if (stree[num].cover != -1)return (stree[num].r-stree[num].l+1)*stree[num].cover;
return counter(num*2)+counter(2*num+1);
}
int main()
{
int t;
scanf("%d", &t);
int nc = 0;
while (t --){
int tot;
scanf("%d", &tot);
creat(1, 1, tot);
int n;
scanf("%d", &n);
int a, b, c;
for (int i = 0; i < n; i ++){
scanf("%d%d%d", &a, &b, &c);
insert(1, a, b, c);
}
printf("Case %d: The total value of the hook is %d.\n", ++nc, counter(1));
}
return 0;
}