hdu1698 Just a Hook

本文介绍了一种使用线段树解决特定区间覆盖问题的方法。通过维护每个线段的颜色信息,并在遇到不同颜色覆盖时转化为混合色,最终计算出整条线段的总价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 又是一道线段树的题目,题目大意就是给你线段[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;   
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值