diff --git a/algorithms/structure/lazy_segment_tree.cpp b/algorithms/structure/lazy_segment_tree.cpp
index 5b8f4d0bc0667742af7c9a346919a8553d4586bf..22f063faa672b45435f977e1a61222c2391cc04f 100644
--- a/algorithms/structure/lazy_segment_tree.cpp
+++ b/algorithms/structure/lazy_segment_tree.cpp
@@ -1,52 +1,43 @@
 /// Lazy Segment Tree
 ///
 /// Time:
-///   - build_tree:  O(n log n)
-///   - update_tree: O(log n)
-///   - query_tree:  O(log n)
+///   - build:  O(n log n)
+///   - update: O(log n)
+///   - query:  O(log n)
 /// Space: O(n)
 
-int N;
-struct LazySegmentTree {
-  vector<int> tree, lazy;
+#define left(x) (x << 1)
+#define right(x) ((x << 1) + 1)
 
-  LazySegmentTree(const vector<int> &v) : 
-    tree(MAX*4), lazy(MAX*4) 
-  {
-    init();
-    build(v);
-  }
+int N;
 
-  void init() {
-    fill(all(tree), 0);
-    fill(all(lazy), 0);
-  }
+template <typename T>
+struct LazySegmentTree {
+  vector<T> tree, lazy;
 
-  inline int left(int x) { return (x << 1); }
-  inline int right(int x) { return (x << 1) + 1; }
+  LazySegmentTree(const vector<T> &v) : 
+    tree(MAX*4, 0), lazy(MAX*4, 0) 
+  { build(v); }
 
-  void build(const vector<int> &v, int node = 1, 
-      int a = 0, int b = N - 1) 
+  void build(const vector<T> &v, 
+      int node = 1, int l = 0, int r = N - 1) 
   {
-    if (a > b) 
-      return;
-
-    if (a == b) {
-      tree[node] = v[a];
-      return;
+    if (l > r) return;
+
+    if (l == r)
+      tree[node] = v[l];
+    else {
+      int m = (l + r) / 2;
+      build(v, left(node), l, m);
+      build(v, right(node), m + 1, r);
+      tree[node] = tree[left(node)] + tree[right(node)];
     }
-
-    int mid = (a + b) / 2;
-    build(v, left(node), a, mid);
-    build(v, right(node), mid + 1, b);
-    tree[node] = tree[left(node)] + tree[right(node)];
   }
 
-  void push(int node, int a, int b, int val) {
-    tree[node] += val;
-    // tree[node] += (b - a + 1)*val; (for Range Sum Query)
+  void push(int node, int l, int r, T val) {
+    tree[node] += (r - l + 1)*val;
 
-    if (a != b) {
+    if (l != r) {
       lazy[left(node)] += val;
       lazy[right(node)] += val;
     }
@@ -54,41 +45,38 @@ struct LazySegmentTree {
     lazy[node] = 0;
   }
 
-  void update(int i, int j, int val, int node = 1,
-      int a = 0, int b = N - 1) 
+  void update(int i, int j, T val, 
+      int node = 1, int l = 0, int r = N - 1) 
   {
     if (lazy[node] != 0)
-      push(node, a, b, lazy[node]);
+      push(node, l, r, lazy[node]);
 
-    if (a > b || a > j || b < i) 
-      return;
+    if (l > r || l > j || r < i) return;
 
-    if (i <= a && b <= j) {
-      push(node, a, b, val);
-      return;
+    if (i <= l && r <= j)
+      push(node, l, r, val);
+    else {
+      int m = (l + r) / 2;
+      update(i, j, val, left(node), l, m);
+      update(i, j, val, right(node), m + 1, r);
+      tree[node] = tree[left(node)] + tree[right(node)];
     }
-
-    int mid = (a + b) / 2;
-    update(i, j, val, left(node), a, mid);
-    update(i, j, val, right(node), mid + 1, b);
-    tree[node] = tree[left(node)] + tree[right(node)];
   }
 
-  int query(int i, int j, int node = 1,
-      int a = 0, int b = N - 1)
+  T query(int i, int j, 
+      int node = 1, int l = 0, int r = N - 1)
   {
-    if (a > b || a > j || b < i)
-      return 0;
+    if (l > r || l > j || r < i) return 0;
 
     if (lazy[node])
-      push(node, a, b, lazy[node]);
+      push(node, l, r, lazy[node]);
 
-    if (a >= i && b <= j)
+    if (l >= i && r <= j)
       return tree[node];
 
-    int mid = (a + b) / 2;
-    int q1 = query(i, j, left(node), a, mid);
-    int q2 = query(i, j, right(node), mid + 1, b);
+    int m = (l + r) / 2;
+    T q1 = query(i, j, left(node), l, m);
+    T q2 = query(i, j, right(node), m + 1, r);
     return q1 + q2;
   }
 };
diff --git a/algorithms/structure/policy_tree.cpp b/algorithms/structure/policy_tree.cpp
index e421ffa08ce53a1ac89f61a5c68a5b906a222f98..9e06d9b8d4b0e2ca627bb863c440c90ed1569bc1 100644
--- a/algorithms/structure/policy_tree.cpp
+++ b/algorithms/structure/policy_tree.cpp
@@ -12,24 +12,20 @@
 
 #include <ext/pb_ds/assoc_container.hpp>
 #include <ext/pb_ds/tree_policy.hpp>
-
 using namespace __gnu_pbds;
 
-typedef tree<
-  int, 
-  null_type, 
-  less<int>, 
-  rb_tree_tag, 
-  tree_order_statistics_node_update
-> set_t;
+template <typename T>
+using ordered_set =
+    tree<T, null_type, less<T>, rb_tree_tag, 
+    tree_order_statistics_node_update>;
 
 void operations() {
-  set_t S;
+  ordered_set S;
 
   S.insert(x);
   S.erase(x);
 
-  // Return iterator to the k-th largest element 
+  // Return iordered_set terator to the k-th largest element 
   // (counting from zero)
   int pos = *S.find_by_order(k);
 
diff --git a/algorithms/structure/segment_tree.cpp b/algorithms/structure/segment_tree.cpp
index b889aae5ab41c692467945c4471b2f7ce3917e65..b2ee9399498df82219892276be3a859111d68ae4 100644
--- a/algorithms/structure/segment_tree.cpp
+++ b/algorithms/structure/segment_tree.cpp
@@ -10,20 +10,19 @@
 ///   - Provide identity value if necessary (default is T())
 
 // Example: SegmentTree<int,plus<int>> seg(n)
-template <typename T, typename OpType = T(*)(T&, T&)>
+template <typename T, typename OT = T(*)(T&, T&)>
 struct SegmentTree {
   int N;
   T ident;
-  OpType op;
+  OT op;
   vector<T> tree;
 
-  SegmentTree(int N, T ident = T()) : 
-    N(N), ident(ident), tree(2 * N, ident) {}
+  SegmentTree(int N, T id = T()) : 
+    N(N), ident(id), tree(2 * N, id) {}
 
   void update(int idx, T val) {
     idx += N;
     tree[idx] = val;
-
     for (; idx > 1; idx >>= 1)
       tree[idx >> 1] = op(tree[idx & ~1], tree[idx | 1]);
   }
@@ -31,12 +30,10 @@ struct SegmentTree {
   T query(int l, int r) {
     T ra = ident, rb = ident;
     l += N, r += N;
-
     for (; l < r; l >>= 1, r >>= 1) {
       if (l & 1) ra = op(ra, tree[l++]);
       if (r & 1) rb = op(tree[--r], rb);
     }
-
     return op(ra, rb);
   }
 };
diff --git a/algorithms/structure/segment_tree_2d.cpp b/algorithms/structure/segment_tree_2d.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dbe716ba211a0d9df6a3ded2bc2a72e305fdb497
--- /dev/null
+++ b/algorithms/structure/segment_tree_2d.cpp
@@ -0,0 +1,112 @@
+/// 2D Segment Tree
+///
+/// Time:
+///   - build:  O(n * m * log n * log m)
+///   - update: O(log n * log m)
+///   - query:  O(log n * log m)
+/// Space: O(16 * n * m)
+///
+/// Caution:
+///   - Very high constant in space complexity
+
+#define left(x) (x << 1)
+#define right(x) ((x << 1) + 1)
+
+int N, M;
+
+template<typename T>
+struct SegmentTree2D {
+  vector<vector<T>> tree;
+
+  SegmentTree2D(const vector<vector<T>> &mat) :
+    tree(4*MAX, vector<T>(4*MAX, 0))
+  { build(mat); }
+
+  void build_row(const vector<vector<T>> &mat, 
+      int ni, int li, int ri,
+      int nj = 1, int lj = 0, int rj = M - 1)
+  {
+    if (lj == rj) {
+      if (li == ri) 
+        tree[ni][nj] = mat[li][lj];
+      else 
+        tree[ni][nj] = tree[left(ni)][nj] + tree[right(ni)][nj];
+    } else {
+      int m = (lj + rj) / 2;
+      build_row(mat, ni, li, ri, left(nj), lj, m);
+      build_row(mat, ni, li, ri, right(nj), m+1, rj);
+      tree[ni][nj] = tree[ni][left(nj)] + tree[ni][right(nj)];
+    }
+  }
+
+  void build(const vector<vector<T>> &mat,
+      int ni = 1, int li = 0, int ri = N - 1) 
+  {
+    if (li != ri) {
+      int m = (li + ri) / 2;
+      build(mat, left(ni), li, m);
+      build(mat, right(ni), m+1, ri);
+    }
+    build_row(mat, ni, li, ri);
+  }
+
+  T query_row(int j1, int j2, int i,
+      int nj = 1, int lj = 0, int rj = M - 1) 
+  {
+    if (lj > rj || lj > j2 || rj < j1) return 0;
+
+    if (j1 <= lj && rj <= j2)
+      return tree[i][nj];
+
+    int m = (lj + rj) / 2;
+    T q1 = query_row(j1, j2, i, left(nj), lj, m);
+    T q2 = query_row(j1, j2, i, right(nj), m + 1, rj);
+    return q1 + q2;
+  }
+
+  T query(int i1, int j1, int i2, int j2,
+      int ni = 1, int li = 0, int ri = N - 1) 
+  {
+    if (li > ri || li > i2 || ri < i1) return 0;
+
+    if (i1 <= li && ri <= i2)
+      return query_row(j1, j2, ni);
+
+    int m = (li + ri) / 2;
+    T q1 = query(i1, j1, i2, j2, left(ni), li, m);
+    T q2 = query(i1, j1, i2, j2, right(ni), m + 1, ri);
+    return q1 + q2;
+  }
+
+  void update_row(int i, int j, T val,
+      int ni, int li, int ri,
+      int nj = 1, int lj = 0, int rj = M - 1)
+  {
+    if (lj > rj || lj > j || rj < j) return;
+
+    if (lj == rj) {
+      if (li == ri) 
+        tree[ni][nj] = val;
+      else 
+        tree[ni][nj] = tree[left(ni)][nj] + tree[right(ni)][nj];
+    } else {
+      int m = (lj + rj) / 2;
+      update_row(i, j, val, ni, li, ri, left(nj), lj, m);
+      update_row(i, j, val, ni, li, ri, right(nj), m+1, rj);
+      tree[ni][nj] = tree[ni][left(nj)] + tree[ni][right(nj)];
+    }
+  }
+
+  void update(int i, int j, T val, 
+      int ni = 1, int li = 0, int ri = N - 1) 
+  {
+    if (li > ri || li > i || ri < i) return;
+
+    if (li != ri) {
+      int m = (li + ri) / 2;
+      update(i, j, val, left(ni), li, m);
+      update(i, j, val, right(ni), m+1, ri);
+    }
+    update_row(i, j, val, ni, li, ri);
+  }
+};