用线段树求区间分段问题

问题:在X轴上的覆盖n条各种颜色(可以相同)一定长度的线段,问X轴被分成多少个段?

分析: 定义cover如下:cover=-1表示该区间由多种颜色组成。cover>=0表示该区间只有一种单一的颜色cover。

 

插入算法:

 void insert(int i, int l, int r, int color)     //将区间[l,r]的颜色改为color
{
    int mid;
    if (tree[i].cover == color) return;     //如果结点i的颜色已经是color,返回,这句可不要
    if (tree[i].b == l && tree[i].e == r)   //如果区间和结点重合,则直接染色
       tree[i].cover = color;
    else
    {
        mid = (tree[i].b+tree[i].e)/2;
        if (tree[i].cover >=0)                        //如果结点区间为单色
        {
            tree[i*2].cover = tree[i].cover;      //颜色先传递给子结点,因为子结点以前未染色
            tree[i*2+1].cover = tree[i].cover;
            tree[i].cover = -1;                        //结点区间为杂色
        }
   
        if (r <= mid)
          insert(2*i, l, r , color);        //只在左子染色
        else if (l >= mid)
          insert(2*i+1, l, r, color);       //只在右子染色
        else                                       //二分
        {
            insert(2*i, l, mid, color);
            insert(2*i+1, mid, r, color);
        }
    }
}

 

统计算法:

int cnt(int i, int &lc, int &rc)  //lc:左儿子颜色, rc:右儿子颜色
{
 int ret, tl, tr, j, k;
 if (tree[i].cover >= 0)         //处理单一颜色
 {
     lc = tree[i].cover;
     rc = tree[i].cover;
     if (tree[i].cover > 0)
        return 1;
     else
        return 0;
 }
 j = cnt(i*2, lc, tl);              //把传入参数lc, rc作为递归参数进一步传递非常有用,它保证了lc, rc能取得离中点mid最近的单色区间的颜色值,以便后面判断是否需要-1
 k = cnt(i*2+1, tr, rc);
 ret = j+k;
 if (tl == tr && tl > 0)   //连接处颜色相同并且非底色,则总数减1
   ret--;
 return ret;
}

 

这个题在分析统计算法时,学生有疑问,然后我们一起研究,发现j = cnt(i*2, lc, tl)中的lc的作用很关键。作为引用型参数,它可以把递归调用中的里层实例的值带回本层,又会进一步把本层的值继续往外层传。于是,从本层的角度看,lc和rc实际了得到了离中间点mid最近的左右两个单色区间的颜色值。如果它们相等,则颜色区间个数要-1.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值