diff --git a/algorithms/graph/floyd_warshall.cpp b/algorithms/graph/floyd_warshall.cpp
index d84545f831be5a1e548520c9e4f087e692c00db9..528d1a667a774ef04c7e5611b28224026ff24331 100644
--- a/algorithms/graph/floyd_warshall.cpp
+++ b/algorithms/graph/floyd_warshall.cpp
@@ -12,7 +12,7 @@ struct FloydWarshall {
   FloydWarshall(int N) :
     N(N) {}
 
-  int run() {
+  void run() {
     for (int i = 0; i < N; ++i)
       for (int j = 0; j < N; ++j)
         dist[i][j] = graph[i][j];
@@ -21,6 +21,6 @@ struct FloydWarshall {
       for (int i = 0; i < N; ++i)
         for (int j = 0; j < N; ++j)
           dist[i][j] = min(dist[i][j], 
-              dist[i][k] + dist[k][j])
+              dist[i][k] + dist[k][j]);
   }
 };
diff --git a/algorithms/math/gale_shapley.cpp b/algorithms/math/gale_shapley.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6009274b8ffcc675b34e5a65f9d3e708d52c308f
--- /dev/null
+++ b/algorithms/math/gale_shapley.cpp
@@ -0,0 +1,70 @@
+/// Gale-Shapley (Stable Marriage)
+///
+/// Description:
+///   Two groups, each of size N are given: men and women. Each person has a
+/// list of preference ranking all N people of the opposite sex. The task is to
+/// unite both groups into stable pairs. A set of pairs is stable if there are
+/// no unassigned couple that like each other more than their assigned pair.\par
+///   The algorithm's steps are: 1) allow every men to propose to their highest
+/// ranking woman; 2) the women become tentatively engaged to their top choice
+/// of men; 3) all rejected men propose to their next choice; 4) the woman
+/// replaces their current pair in case a man with a higher rank proposes to
+/// her, the replaced men are now marked as rejected; 5) repeat step 3 until
+/// all men are paired.
+///
+/// Time: O(n^2)
+/// Space: O(n^2)
+///
+/// Caution:
+///   - Men are indexed by [0..N)
+///   - Women are indexed by [N..2N)
+///   - The result prioritizes men, swapping the bottom half
+///   of the matrix by the top half will invert who's given
+///   preference
+///
+/// Status: Tested (URI1852)
+
+// Receives matrix of preferences pref[2*N][N] and returns
+// vector v where v[m] contains preference of the m-th man.
+vector<int> gale_shapley(const vector<vector<int>> &pref) {
+  int n = pref[0].size();
+  vector<int> w_part(n, -1);
+  vector<int> m_part(n, -1);
+  vector<int> start(n, 0);
+  
+  while (true) {
+    int m;
+    for (m = 0; m < n; ++m)
+      if (m_part[m] == -1) 
+        break;
+
+    if (m == n) break;
+
+    for (; start[m] < n && m_part[m] == -1; ++start[m]) {
+      int w = pref[m][start[m]];
+
+      if (w_part[w - n] == -1) {
+        w_part[w - n] = m;
+        m_part[m] = w;
+      } else {
+        int m1 = w_part[w - n];
+        bool pref_m = false;
+
+        for (int j = 0; j < n; ++j)
+          if (pref[w][j] == m) {
+            pref_m = true;
+            break;
+          } else if (pref[w][j] == m1)
+            break;
+
+        if (pref_m) {
+          w_part[w - n] = m;
+          m_part[m] = w;
+          m_part[m1] = -1;
+        }
+      }
+    }
+  }
+
+  return m_part;
+}
diff --git a/algorithms/structure/segment_tree.cpp b/algorithms/structure/segment_tree.cpp
index 3eb3784c5e233734d4c839f9baf6312ac723ae3f..77f82655b21bf2de8195f4f6c07de1a88dc54875 100644
--- a/algorithms/structure/segment_tree.cpp
+++ b/algorithms/structure/segment_tree.cpp
@@ -4,42 +4,37 @@
 ///   - update: O(log n)
 ///   - query:  O(log n)
 /// Space: O(n)
+///
+/// Caution:
+///   - Query returns op([l..r))
+///   - Provide identity value if necessary (default is T())
 
+// Example: SegmentTree<int,plus<int>> seg(n)
+template <typename T, typename OpType = T(*)(T&, T&)>
 struct SegmentTree {
   int N;
-  vector<int> tree;
-
-  Tree(int N) : 
-    N(N), tree(2 * N, 0) {}
+  T ident;
+  OpType op;
+  vector<T> tree;
 
-  // Base depends on 'op':
-  // op: a + b -> base: 0
-  // op: min(a,b) -> base: inf
-  int base = -inf;
-  int op(int a, int b) { 
-    return max(a, b); 
-  }
+  SegmentTree(int N, T ident = T()) : 
+    N(N), ident(ident), tree(2 * N, ident) {}
 
-  void update(int idx, int val) {
+  void update(int idx, T val) {
     idx += N;
     tree[idx] = val;
 
-    while (idx > 1) {
-      tree[idx / 2] = op(tree[idx & ~1], tree[idx | 1]);
-      idx /= 2;
-    }
+    for (; idx > 1; idx >>= 1)
+      tree[idx >> 1] = op(tree[idx & ~1], tree[idx | 1]);
   }
 
-  int query(int l, int r) {
-    int ra = base, rb = base;
+  T query(int l, int r) {
+    T ra = ident, rb = ident;
     l += N, r += N;
 
-    while (l < r) {
-      if (l % 2) ra = op(ra, tree[l++]);
-      if (r % 2) rb = op(tree[--r], rb);
-
-      l >>= 1;
-      r >>= 1;
+    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/caderno.pdf b/caderno.pdf
index 53d0190a3a5725ada0d5ed98b3b139107b0916d9..0be09685d4ca6d5c8ad92e21ee518a0f3077b01d 100644
Binary files a/caderno.pdf and b/caderno.pdf differ
diff --git a/contests/Cadernaveis/URI1852.cpp b/contests/Cadernaveis/URI1852.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f33593107155cfa994cdfeb9b17ded41735ba72f
--- /dev/null
+++ b/contests/Cadernaveis/URI1852.cpp
@@ -0,0 +1,115 @@
+#include <bits/stdc++.h>
+
+#define EPS 1e-6
+#define MOD 1000000007
+#define inf 0x3f3f3f3f
+#define llinf 0x3f3f3f3f3f3f3f3f
+
+#define fi first
+#define se second
+#define pb push_back
+#define ende '\n'
+
+#define all(x) (x).begin(), (x).end()
+#define rall(x) (x).rbegin(), (x).rend()
+#define mset(x, y) memset(&x, (y), sizeof(x))
+
+using namespace std; 
+
+using ll = long long;
+using ii = pair<int,int>;
+
+vector<int> gale_shapley(const vector<vector<int>> &pref) {
+  int n = pref[0].size();
+  vector<int> w_part(n, -1);
+  vector<int> m_part(n, -1);
+  vector<int> start(n, 0);
+  
+  while (true) {
+    int m;
+    for (m = 0; m < n; ++m)
+      if (m_part[m] == -1) 
+        break;
+
+    if (m == n) break;
+
+    for (; start[m] < n && m_part[m] == -1; ++start[m]) {
+      int w = pref[m][start[m]];
+
+      if (w_part[w - n] == -1) {
+        w_part[w - n] = m;
+        m_part[m] = w;
+      } else {
+        int m1 = w_part[w - n];
+        bool pref_m = false;
+
+        for (int j = 0; j < n; ++j)
+          if (pref[w][j] == m) {
+            pref_m = true;
+            break;
+          } else if (pref[w][j] == m1)
+            break;
+
+        if (pref_m) {
+          w_part[w - n] = m;
+          m_part[m] = w;
+          m_part[m1] = -1;
+        }
+      }
+    }
+  }
+
+  return m_part;
+}
+
+int main() {
+  ios::sync_with_stdio(0);
+  cin.tie(0);
+
+  int n; cin >> n;
+  vector<vector<int>> pref(2*n, vector<int>(n));
+
+  int k1 = 0, k2 = n;
+  map<string,int> M;
+  vector<string> names(2*n);
+  for (int i = 0; i < n; ++i) {
+    string s; cin >> s;
+    if (M.find(s) == M.end()) {
+      names[k1] = s;
+      M[s] = k1++;
+    }
+
+    for (int j = 0; j < n; ++j) {
+      string t; cin >> t;
+      if (M.find(t) == M.end()) {
+        names[k2] = t;
+        M[t] = k2++;
+      }
+
+      pref[M[s]][j] = M[t];
+    }
+  }
+
+  for (int i = 0; i < n; ++i) {
+    string s; cin >> s;
+    if (M.find(s) == M.end()) {
+      names[k2] = s;
+      M[s] = k2++;
+    }
+
+    for (int j = 0; j < n; ++j) {
+      string t; cin >> t;
+      if (M.find(t) == M.end()) {
+        names[k1] = t;
+        M[t] = k1++;
+      }
+
+      pref[M[s]][j] = M[t];
+    }
+  }
+
+  vector<int> ans = gale_shapley(pref);
+  for (int i = 0; i < n; ++i)
+    cout << names[i] << " " << names[ans[i]] << ende;
+  return 0;
+}