More than code

More Than Code
The efficiency of your iteration of reading, practicing and thinking decides your understanding of the world.
  1. 首页
  2. 未分类
  3. 正文

Rust ODT

2022年6月20日 681点热度 1人点赞 0条评论

Rust ODT

ODT主要处理的是包含区间赋值的问题。以前的名字叫Old Driver Tree。核心思路就是通过随机数据的情况下,区间赋值的操作可以合并很多区间为一个整块。我们通过三元组的形式,即left,right,value来表示区间。在查询的时候就只查询范围内的三元组。由于区间赋值可以合并区间,所以总共要查询的数量很少。

可以从这道题来了解这个数据结构

ODT的核心就是两个函数。一个是split,将我们维护的区间中在一个点处断开。还有一个是assign,即区间赋值

fn split(&mut self, pos: i32) {
    use std::ops::Bound::*;
    let tmp = Node { l: pos, r: 0, v: 0 };
    if let Some(node) = self.set.range((Included(&tmp), Unbounded)).next() {
        if node.l == pos {
            return;
        }
    }
    let it = self.set.range((Unbounded, Excluded(&tmp))).next_back().unwrap();
    let &Node{ l, r, v } = it;
    self.set.remove( &Node { l: l, r: r, v: v });
    self.set.insert( Node { l: l, r: pos - 1, v: v});
    self.set.insert( Node { l: pos, r: r, v: v });
}

先通过lowerbound查找这个点是不是已经被断开了。如果是直接返回就行。

否则的话我们找到包含这个点的那个区间,将它删除,并插入断开后的区间。

fn assign(&mut self, l: i32, r: i32, v: i32) {
    use std::ops::Bound::*;
    self.split(r + 1);
    self.split(l);
    let tmp_l = Node { l: l, r: 0, v: 0 };
    let tmp_r = Node { l: r + 1, r: 0, v: 0 };
    let iter: Vec<Node> = self.set.range((Included(&tmp_l), Excluded(&tmp_r))).map(|node| node.clone()).collect();
    for node in iter.iter() {
        self.set.remove( node );
    }
    self.set.insert( Node { l: l, r: r, v: v });
}

区间赋值上,这里是[l, r],所以从r + 1和l中断开。这样我们的区间就会变成[l, x1], [x1, x2], ..., [xn, r], [r + 1, y]。我们删除中间这一段,并让[l, r] = v替换他

查询的时候也需要断开区间,然后查询[l, r]中的三元组即可

这里的设置有一个前提,就是区间必须都是有效的。而不能是空的。也就是所有的区间并起来得到的就是整体的值域。

最后看一下整体的代码

use std::collections::BTreeSet;

#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
struct Node {
    l: i32,
    r: i32,
    v: i32
}

struct RangeModule {
    set: BTreeSet<Node>,
}

impl RangeModule {
    fn new() -> Self {
        let mut set = BTreeSet::new();
        set.insert( Node { l: 1, r: 1e9 as i32, v: 0 });
        Self {
            set: set
        }
    }

    fn split(&mut self, pos: i32) {
        use std::ops::Bound::*;
        let tmp = Node { l: pos, r: 0, v: 0 };
        if let Some(node) = self.set.range((Included(&tmp), Unbounded)).next() {
            if node.l == pos {
                return;
            }
        }
        let it = self.set.range((Unbounded, Excluded(&tmp))).next_back().unwrap();
        let &Node{ l, r, v } = it;
        self.set.remove( &Node { l: l, r: r, v: v });
        self.set.insert( Node { l: l, r: pos - 1, v: v});
        self.set.insert( Node { l: pos, r: r, v: v });
    }

    fn assign(&mut self, l: i32, r: i32, v: i32) {
        use std::ops::Bound::*;
        self.split(r + 1);
        self.split(l);
        let tmp_l = Node { l: l, r: 0, v: 0 };
        let tmp_r = Node { l: r + 1, r: 0, v: 0 };
        let iter: Vec<Node> = self.set.range((Included(&tmp_l), Excluded(&tmp_r))).map(|node| node.clone()).collect();
        for node in iter.iter() {
            self.set.remove( node );
        }
        self.set.insert( Node { l: l, r: r, v: v });
    }

    fn check(&mut self, l: i32, r: i32) -> bool {
        use std::ops::Bound::*;
        self.split(r + 1);
        self.split(l);
        let tmp_l = Node { l: l, r: 0, v: 0 };
        let tmp_r = Node { l: r + 1, r: 0, v: 0 };
        for node in self.set.range((Included(&tmp_l), Excluded(&tmp_r))) {
            if node.v == 0 {
                return false;
            }
        }
        return true;
    }

    fn add_range(&mut self, left: i32, right: i32) {
        self.assign(left, right - 1, 1);
    }

    fn query_range(&mut self, left: i32, right: i32) -> bool {
        return self.check(left, right - 1);
    }

    fn remove_range(&mut self, left: i32, right: i32) {
        self.assign(left, right - 1, 0);
    }
}
标签: 暂无
最后更新:2022年6月20日

sheep

think again

点赞
< 上一篇
下一篇 >

文章评论

取消回复

COPYRIGHT © 2021 heavensheep.xyz. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS