初识线段树(线段树总结)

线段树的最基本的操作

[1]  建树 :

void construct(int left, int right){
    int index, mid;
    node++;
    index = node;
    leftvalue[index] = left;
    rightvalue[index] = right;
    cover[index] = 0;
    if(left + 1 < right){
        mid = (left + right) / 2;
        leftchild[index] = node + 1;
        construct(left, mid);
        rightchild[index] = node + 1;
        construct(mid, right);
    }
}


上述代码利用二分的方法,建立一棵叶子节点为 (i, i+ 1)的线段树 。 特点是每棵树的根,一定包含于子树的线段。






[2] 插入一段线段:

void insert(int index, int c, int d){
    int mid;
    if(c <= leftvalue[index] && rightvalue[index] <= d)cover[index]++;
    else{
        if(leftvalue[index] + 1 < rightvalue[index]){
            mid = (leftvalue[index] + rightvalue[index]) / 2;
            if(c < mid)insert(leftchild[index], c, d);
            if(d > mid)insert(rightchild[index], c, d);
        }
    }
}


解释 :当要插入的线段[c, d] 覆盖了线段树上的某段线段的时候,将其标记覆盖的cover[]数组自加。如果不覆盖该线段,分为三种情况,可自己画          一下,再根据当前线段于要插入线段的关系,分情况递归左右子树



if(c <= leftvalue[index] && rightvalue[index] <= d)

cover[index]++;


 c < mid  && d< mid   

if(c < mid)insert(leftchild[index], c, d);


c > mid && d >mid  运行

if(d > mid)insert(rightchild[index], c, d);



c < mid && d > mid 运行

if(c < mid)insert(leftchild[index], c, d);
if(d > mid)insert(rightchild[index], c, d);



[3]删除一段线段:

void Delete(int index, int c, int d){
    int mid;
    if(c <= leftvalue[index] && rightvalue[index] <= d && cover[index])
        cover[index]--;
    else{
        if(leftvalue[index] + 1 < rightvalue[index]){
            mid = (leftvalue[index] + rightvalue[index]) / 2;
            if(c < mid)Delete(leftchild[index], c, d);
            if(d > mid)Delete(rightchild[index], c, d);
        }
    }
}


与插入一样理解。




[4] 统计:

关于统计,有很多,也很灵活,对于每个题目来说,线段树内每个节点内的要表示的有很多,很灵活,这里只说说测度,也就是最后被覆盖的线段的总长度

void count(int index){
    if(cover[index] > 0)total += y[rightvalue[index]] - y[leftvalue[index]];
    else{
        if(leftvalue[index] + 1 < rightvalue[index]){
            count(leftchild[index]);
            count(rightchild[index]);
        }
    }
}


理解 :既然某段线段的cover[]是正数,那么,它的子树也一定被cover,因为前面说过的“特点是每棵树的根,一定包含于子树的线段”
所以长度 = 右边界 - 左边界;

以上为线段树的最基本的操作,是对长度的操作。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值