diff --git a/.verify-helper/timestamps.remote.json b/.verify-helper/timestamps.remote.json
index e3dcf058..2d3a3bf9 100644
--- a/.verify-helper/timestamps.remote.json
+++ b/.verify-helper/timestamps.remote.json
@@ -21,7 +21,8 @@
 "combinatorial_opt/test/simplex.multiprecision.test.cpp": "2021-02-28 16:53:36 +0900",
 "combinatorial_opt/test/simplex.shortestpath.test.cpp": "2021-02-28 16:53:36 +0900",
 "convex_hull_trick/test/convex_hull_trick.test.cpp": "2020-11-18 20:33:55 +0900",
-"convex_hull_trick/test/li_chao_tree.test.cpp": "2021-09-16 00:36:41 +0900",
+"convex_hull_trick/test/li_chao_tree.test.cpp": "2021-09-20 19:53:17 +0900",
+"convex_hull_trick/test/monotone-insert-get_cht.test.cpp": "2021-09-20 20:03:18 +0900",
 "convolution/test/bitwise_and_conv.test.cpp": "2021-06-06 14:54:00 +0900",
 "convolution/test/bitwise_xor_conv.test.cpp": "2021-06-06 14:54:00 +0900",
 "convolution/test/hadamard_xor.test.cpp": "2020-12-20 04:05:21 +0900",
diff --git a/convex_hull_trick/add-get-monotone_cht.hpp b/convex_hull_trick/add-get-monotone_cht.hpp
deleted file mode 100644
index f27d6067..00000000
--- a/convex_hull_trick/add-get-monotone_cht.hpp
+++ /dev/null
@@ -1,69 +0,0 @@
-#pragma once
-#include <cassert>
-#include <list>
-#include <utility>
-
-// CUT begin
-// Convex Hull Trick for monotone increasing queries, monotone decreasing slopes
-// Each operation is amortized O(1)
-// - is_minimizer: if true, calculates min. Otherwise, calculates max.
-// - add_line(a, b): Add `y = ax + b`, a must be monotone decreasing (if is_minimizer == true) / increasing (otherwise)
-// - add_convex_parabola(c, a, b): Add `y = c(x - a)^2 + b`, c is constant, a is monotone increasing (if is_minimizer == true) / decreasing (otherwise)
-// - get(x): Calculate min/max. value of `y = ax + b`'s at point x, x must be monotone increasing FOR BOTH CASES.
-// - parabola_get(c, x): Caclculate min/max. value of `y = c(x - a)^2 + b`'s, x must be monotone increasing FOR BOTH CASES.
-// - If you need random access, change `std::list` to `std::deque`
-// Verified: <https://yukicoder.me/submissions/409156>
-template <bool is_minimizer, typename T_CHT = long long, typename T_MP = __int128, T_CHT INF = 1LL << 61>
-struct MonotoneConvexHullTrick : std::list<std::pair<T_CHT, T_CHT>> // (a, b) means `y = ax + b`
-{
-    MonotoneConvexHullTrick() = default;
-    void add_line(T_CHT a, T_CHT b) { // Add y = ax + b
-        if (!is_minimizer) a = -a, b = -b;
-        assert(this->empty() or this->back().first >= a);
-        while (this->size() > 1u) {
-            if (this->back().first == a) {
-                if (this->back().second <= b) {
-                    return;
-                } else {
-                    this->pop_back();
-                    continue;
-                }
-            }
-            auto ill = std::prev(this->end(), 2);
-            auto l = (T_MP)(this->back().second - ill->second) * (this->back().first - a); // Overflow might occur here.
-            auto r = (T_MP)(b - this->back().second) * (ill->first - this->back().first);
-            if (l < r) break;
-            this->pop_back();
-        }
-        this->emplace_back(a, b);
-    }
-    T_CHT get(T_CHT x) {
-        while (this->size() > 1u and
-               this->begin()->first * x + this->begin()->second >= (++this->begin())->first * x + (++this->begin())->second)
-            this->pop_front();
-        return (this->empty() ? INF : this->begin()->first * x + this->begin()->second) * (is_minimizer ? 1 : -1);
-    }
-    void add_convex_parabola(T_CHT c, T_CHT a, T_CHT b) { add_line(c * a * (-2), c * a * a + b); }
-    T_CHT parabola_get(T_CHT c, T_CHT x) { return get(x) + c * x * x; }
-
-    static MonotoneConvexHullTrick merge(const MonotoneConvexHullTrick &cht1, const MonotoneConvexHullTrick &cht2) {
-        MonotoneConvexHullTrick ret;
-        auto i1 = cht1.begin(), i2 = cht2.begin();
-        static const T_CHT sgn = is_minimizer ? 1 : -1;
-        T_CHT a = 0, b = 0;
-        while (i1 != cht1.end() and i2 != cht2.end()) {
-            if (i1->first == i2->first) {
-                a = i1->first, b = std::min(i1->second, i2->second);
-                i1++, i2++;
-            } else if (i1->first > i2->first) {
-                a = i1->first, b = i1->second, i1++;
-            } else {
-                a = i2->first, b = i2->second, i2++;
-            }
-            ret.add_line(a * sgn, b * sgn);
-        }
-        while (i1 != cht1.end()) ret.add_line(i1->first * sgn, i1->second * sgn), i1++;
-        while (i2 != cht2.end()) ret.add_line(i2->first * sgn, i2->second * sgn), i2++;
-        return ret;
-    }
-};
diff --git a/convex_hull_trick/li_chao_tree.hpp b/convex_hull_trick/li_chao_tree.hpp
index e116dbbe..19a20709 100644
--- a/convex_hull_trick/li_chao_tree.hpp
+++ b/convex_hull_trick/li_chao_tree.hpp
@@ -6,7 +6,7 @@
 
 // Li-Chao tree
 // init() : set x's where we will execute get(x) queries
-// add_segment(l, r, a, b): update by ax + b in [l, r)
+// insert_segment(l, r, a, b): update by ax + b in [l, r)
 // get(x): get min
 template <class T, class T_MP> struct li_chao_tree {
     int _n, _head;
@@ -78,12 +78,12 @@ template <class T, class T_MP> struct li_chao_tree {
         }
     }
 
-    void add_line(T a, T b, int idx = -1) {
+    void insert_line(T a, T b, int idx = -1) {
         il = 0, ir = _n;
         if (il >= ir) return;
         _rec(1, 0, _head, _Line{a, b, idx, true});
     }
-    void add_segment(T xl, T xr, T a, T b, int idx = -1) {
+    void insert_segment(T xl, T xr, T a, T b, int idx = -1) {
         il = std::lower_bound(xs.begin(), xs.end(), xl) - xs.begin();
         ir = std::lower_bound(xs.begin(), xs.end(), xr) - xs.begin();
         if (il >= ir) return;
diff --git a/convex_hull_trick/li_chao_tree.md b/convex_hull_trick/li_chao_tree.md
index fad0a37b..b156ed37 100644
--- a/convex_hull_trick/li_chao_tree.md
+++ b/convex_hull_trick/li_chao_tree.md
@@ -13,7 +13,7 @@ vector<long long> xs;
 li_chao_tree<long long, __int128> tree;
 tree.init(xs); // xs が昇順である必要はない
 
-tree.add_segment(l, r, a, b, 0); // chmin by ax + b in [l, r)
+tree.insert_segment(l, r, a, b, 0); // chmin by ax + b in [l, r)
 
 ret = tree.get(x);
 cout << ret.minval << endl;
diff --git a/convex_hull_trick/monotone-insert-get-cht.md b/convex_hull_trick/monotone-insert-get-cht.md
new file mode 100644
index 00000000..b0d6ce0e
--- /dev/null
+++ b/convex_hull_trick/monotone-insert-get-cht.md
@@ -0,0 +1,17 @@
+---
+title: Convex hull trick (monotone insert, monotone get)
+documentation_of: ./monotone-insert-get_cht.hpp
+---
+
+各クエリが償却 $O(1)$.
+
+- `insert_line(T a, T b)` 直線追加クエリ.追加される直線 $y = ax + b$ について,$a$ の値が単調非増加(最小値取得) / 単調非減少(最大値取得).
+- `get(T x)` 最小値・最大値取得クエリ.取得する $x$ 座標は単調非減少.
+
+- `insert_convex_parabola(T c, T a, T b)` 放物線 $y = c(x - a)^2 + b$ の追加クエリ.$c$ の値は全クエリで共通でなければならない.最小値取得の場合,$ca$ の値が単調増加でなければならない.
+- `parabola_get(T c, T x)` 放物線たちの最小値・最大値取得クエリ.取得する $x$ 座標は単調非減少.
+- `merge(CHT cht1, CHT cht2)` 二つの CHT をマージする.計算量は $O(\mathrm{size}(\mathrm{cht1}) + \mathrm{size}(\mathrm{cht2}))$.
+
+## 問題例
+
+- [No.952 危険な火薬庫 - yukicoder](https://yukicoder.me/problems/no/952)
diff --git a/convex_hull_trick/monotone-insert-get_cht.hpp b/convex_hull_trick/monotone-insert-get_cht.hpp
new file mode 100644
index 00000000..ba8f5f9f
--- /dev/null
+++ b/convex_hull_trick/monotone-insert-get_cht.hpp
@@ -0,0 +1,85 @@
+#pragma once
+#include <cassert>
+#include <list>
+#include <utility>
+
+// CUT begin
+// Convex Hull Trick for monotone increasing queries, monotone decreasing slopes
+// Each operation is amortized O(1)
+// - is_minimizer: if true, calculates min. Otherwise, calculates max.
+// - insert_line(a, b): Insert `y = ax + b`,
+//   a must be monotone decreasing (if is_minimizer == true) / increasing (otherwise)
+// - add_convex_parabola(c, a, b): Add `y = c(x - a)^2 + b`, c is constant, a is monotone
+//   increasing (if is_minimizer == true) / decreasing (otherwise)
+// - get(x): Calculate min/max. value of `y = ax + b`'s at point x, x must be monotone
+//   increasing FOR BOTH CASES.
+// - parabola_get(c, x): Caclculate min/max. value of `y = c(x - a)^2 + b`'s, x must be monotone
+//   increasing FOR BOTH CASES.
+// - If you need random access, change `std::list` to `std::deque`
+// Verified: https://yukicoder.me/submissions/409156
+template <bool is_minimizer, class T = long long, class T_MP = __int128, T INF = 1LL << 61>
+class MonotoneConvexHullTrick : std::list<std::pair<T, T>> {
+    // (a, b) means `y = ax + b`
+    T_MP _eval(typename std::list<std::pair<T, T>>::const_iterator itr, T x) {
+        return T_MP(itr->first) * x + itr->second;
+    }
+
+public:
+    MonotoneConvexHullTrick() { static_assert(INF > 0, "INF must be positive."); }
+    void insert_line(T a, T b) { // Add y = ax + b
+        if (!is_minimizer) a = -a, b = -b;
+        assert(this->empty() or this->back().first >= a);
+        while (this->size() > 1u) {
+            if (this->back().first == a) {
+                if (this->back().second <= b) return;
+                this->pop_back();
+                continue;
+            }
+            auto ill = std::prev(this->end(), 2);
+            auto l = (T_MP)(this->back().second - ill->second) * (this->back().first - a);
+            auto r = (T_MP)(b - this->back().second) * (ill->first - this->back().first);
+            if (l < r) break;
+            this->pop_back();
+        }
+        this->emplace_back(a, b);
+    }
+
+    struct Ret {
+        T line_a, line_b;
+        bool is_valid;
+        T_MP val;
+    };
+    Ret get(T x) {
+        if (this->empty()) return {0, 0, false, is_minimizer ? INF : -INF};
+        while (this->size() > 1 and _eval(this->begin(), x) >= _eval(std::next(this->begin()), x)) {
+            this->pop_front();
+        }
+        T_MP val = _eval(this->begin(), x) * (is_minimizer ? 1 : -1);
+        return {(is_minimizer ? 1 : -1) * this->begin()->first,
+                (is_minimizer ? 1 : -1) * this->begin()->second, true, val};
+    }
+    void insert_convex_parabola(T c, T a, T b) { insert_line(c * a * (-2), c * a * a + b); }
+    T_MP parabola_get(T c, T x) { return get(x).val + c * x * x; }
+
+    static MonotoneConvexHullTrick
+    merge(const MonotoneConvexHullTrick &cht1, const MonotoneConvexHullTrick &cht2) {
+        MonotoneConvexHullTrick ret;
+        auto i1 = cht1.begin(), i2 = cht2.begin();
+        static const T sgn = is_minimizer ? 1 : -1;
+        T a = 0, b = 0;
+        while (i1 != cht1.end() and i2 != cht2.end()) {
+            if (i1->first == i2->first) {
+                a = i1->first, b = std::min(i1->second, i2->second);
+                ++i1, ++i2;
+            } else if (i1->first > i2->first) {
+                a = i1->first, b = i1->second, ++i1;
+            } else {
+                a = i2->first, b = i2->second, ++i2;
+            }
+            ret.insert_line(a * sgn, b * sgn);
+        }
+        while (i1 != cht1.end()) ret.insert_line(i1->first * sgn, i1->second * sgn), ++i1;
+        while (i2 != cht2.end()) ret.insert_line(i2->first * sgn, i2->second * sgn), ++i2;
+        return ret;
+    }
+};
diff --git a/convex_hull_trick/test/li_chao_tree.test.cpp b/convex_hull_trick/test/li_chao_tree.test.cpp
index f58eb96e..b16ae291 100644
--- a/convex_hull_trick/test/li_chao_tree.test.cpp
+++ b/convex_hull_trick/test/li_chao_tree.test.cpp
@@ -36,7 +36,7 @@ int main() {
 
     for (auto q : qs) {
         tie(tp, l, r, a, b) = q;
-        if (tp == 0) tree.add_segment(l, r, a, b, 0);
+        if (tp == 0) tree.insert_segment(l, r, a, b, 0);
         if (tp == 1) {
             auto ret = tree.get(l);
             if (ret.is_valid) {
diff --git a/convex_hull_trick/test/monotone-insert-get_cht.test.cpp b/convex_hull_trick/test/monotone-insert-get_cht.test.cpp
new file mode 100644
index 00000000..c78cf154
--- /dev/null
+++ b/convex_hull_trick/test/monotone-insert-get_cht.test.cpp
@@ -0,0 +1,27 @@
+#define PROBLEM "https://yukicoder.me/problems/no/952"
+#include "../monotone-insert-get_cht.hpp"
+#include <iostream>
+#include <vector>
+using namespace std;
+
+int main() {
+    int N;
+    cin >> N;
+    vector<long long> A(N);
+    for (auto &x : A) cin >> x;
+    vector<MonotoneConvexHullTrick<true, long long, __int128>> cht(N + 1);
+    int x = 0;
+    cht[0].insert_convex_parabola(1, x, 0);
+    for (int i = 0; i < N; ++i) {
+        for (int d = i; d >= 0; --d) {
+            long long v = cht[d].parabola_get(1, x);
+            cht[d + 1].insert_convex_parabola(1, x + A[i], v);
+        }
+        x += A[i];
+    }
+    cht.pop_back();
+    while (!cht.empty()) {
+        cout << (long long)cht.back().parabola_get(1, x) << '\n';
+        cht.pop_back();
+    }
+}