Unverified Commit ed60f963 authored by ir1d's avatar ir1d Committed by GitHub
Browse files

Merge pull request #934 from Alpha1022/master

更新珂朵莉树
parents c514976d 09ec02e4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20,3 +20,4 @@
-   矩阵树定理
-   DSU on Tree
-   朱刘算法(并不是最小生成树)
-   珂朵莉树

docs/misc/odt.md

0 → 100644
+95 −0
Original line number Diff line number Diff line
## 名称简介

老司机树,ODT(Old Driver Tree),珂朵莉树(Ctholly Tree)。  
起源自[CF896C](https://codeforces.com/problemset/problem/896/C)

## 前置知识

会用 STL 的 set 就行。

## 核心思想

把值相同的区间合并成一个结点保存在 set 里面。

## 用处

骗分。  
只要是有区间赋值操作的数据结构题都可以用来骗分。  
一般出题人不会**刻意**卡,但是不小心卡了就……

如果要保证复杂度正确,必须保证数据随机。  
证明在[](http://codeforces.com/blog/entry/56135?#comment-398940)

## 正文

首先,结点的保存方式:

```cpp
struct node {
  int l, r;
  mutable int v;
  inline bool operator(const node &o) const { return l < o.l; }
};
```

其中, `int v` 是你自己指定的附加数据。

然后,我们定义一个 `set<node> odt;` 来维护这些结点。  
为简化代码,可以 `typedef set<node>::iterator IT`

### split

最核心的操作之一 `split` ,它用于取得以 $x$ 开头的结点。  
参考代码如下:

```cpp
IT split(int x) {
  if (x > n)
    ;
  return odt.end();
  IT it = --odt.upper_bound((node){x, 0, 0});
  if (it->l == x) return it;
  int l = it->l, r = it->r, v = it->v;
  odt.erase(it);
  odt.insert((node){l, x - 1, v});
  return odt.insert((node){x, r, v}).first;
}
```

这个玩意有什么用呢?  
任何对于 $[l,r]$ 的区间操作,都可以转换成 set 上 $[split(l),split(r + 1))$ 的操作。

### assign

另外一个重要的操作 `assign` 用于对一段区间进行赋值。  
对于 ODT 来说,区间操作只有这个比较特殊,也是保证复杂度的关键。  
如果 ODT 里全是长度为 $1$ 的区间,就成了暴力,但是有了 `assign` ,可以使 ODT 的大小下降。  
参考代码如下:

```cpp
void assign(int l, int r, int v) {
  IT itr = split(r + 1), itl = split(l);
  odt.erase(itl, itr);
  odt.insert((node){l, r, v});
}
```

### 其他操作

套模板就好了,参考代码如下:

```cpp
void performance(int l, int r) {
  IT itr = split(r + 1), itl = split(l);
  for (; itl != itr; ++itl) {
    // Perform here
  }
}
```

## 习题

-   [BZOJ 1858.\[SCOI2010\]序列操作](https://www.lydsy.com/JudgeOnline/problem.php?id=1858)
-   [BZOJ 4592.\[SHOI2015\]脑洞治疗仪](https://www.lydsy.com/JudgeOnline/problem.php?id=4592)
-   [洛谷 2787. 理理思维](https://www.luogu.org/problemnew/show/P2787)
-   [洛谷 4979. 矿洞:坍塌](https://www.luogu.org/problemnew/show/P4979)
+1 −0
Original line number Diff line number Diff line
@@ -252,6 +252,7 @@ nav:
    - 读入、输出优化: misc/io.md
    - 离散化: misc/discrete.md
    - 树上启发式合并: misc/dsu-on-tree.md
    - 珂朵莉树: misc/odt.md

# Theme
theme: