diff --git a/om-graphs/graphs.tex b/om-graphs/graphs.tex
index 5ccc92e2e9e1f61a56392503cbf655317f9d01b0..15e52bcb3c7fb5d90a6700b157cda3799a681e07 100644
--- a/om-graphs/graphs.tex
+++ b/om-graphs/graphs.tex
@@ -4,6 +4,8 @@
 \fi
 
 \def\TODO{{\bf TODO}}
+\def\LCA{\op{LCA}}
+
 
 \chapter[graphs]{Representation of graphs}
 In this chapter we will peek into the area of data structures for representation of
@@ -16,28 +18,30 @@ E)$, where each vertex~$v$ has weight~$w(v)\in\R$.\foot{We could also had weight
 instead.} We would like to support following operations:
 \tightlist{o}
 \:\em{path query}   --- find the vertex with minimum weight on a path $u\to
-v$;\foot{Generally, we can use any associative operation, instead of minimum.}
+v$;\foot{Generally, we can use any associative operation instead of minimum.}
 \:\em{point update} --- set $w(v) \leftarrow c\in\R$;
 \:\em{path update}  --- increase weight of each vertex on path $u\to v$ by $\delta\in\R$;
 \:\em{structural update} --- connect/disconnect two trees via edge $(u,v)$.
 \endlist
 
+
 \section[path]{Static path}
-As a warm-up we build a data structure for $F$ being a path and without structural
+As a warm-up we build a data structure for $F$ being a static path, without structural
 updates. This will also be an important building block for the more general case.
 
 Let us denote the vertices $v_1, \dots, v_n$ according to the position on the path and let
-us denote $w_i = w(v_i)$. \TODO\foot{maybe change initial notation} We build an interval
+us denote $w_i = w(v_i)$. \TODO\foot{maybe change initial notation} We build an range
 tree~$T$ over the weights $w_1, \dots, w_n$. That is, $T$ is a complete binary tree with
 $w_1,\dots w_n$ in its leaves (in this order) and inner nodes contain the minimum of their
 children. Note that each node represents a subpath of~$F$ with leaves being the single
 vertices. 
 
-\TODO picture of path and the interval tree
-\figure[]{interval-tree.pdf}{}{\TODO}
+\TODO perhaps reference the lecture notes on details about range trees
+\TODO picture of path and the range tree
+\figure[]{range-tree.pdf}{}{\TODO}
 % temporary sketch, not in repository
 
-\theorem{Static path representation via interval tree can perform \em{path query},
+\theorem{Static path representation via range tree can perform \em{path query},
 \em{point update}
 and \em{path update} in $\O(\log n)$ time.
 }
@@ -73,4 +77,66 @@ always traverse the tree top-down in order to see correct values in the nodes.
 % temporary sketch, not in repository
 \qed
 
+
+\section[hld]{Heavy-light decomposition}
+Now we are ready build data structure for static trees using \em{heavy-light
+decomposition}. We assume our tree $F$ is rooted and we orient all edges
+up, towards the root \TODO\foot{maybe unnecessary now}.
+
+\defn{
+Let~$F$ be a rooted tree. For any vertex~$v$ we define $s(v)$ to be the size of subtree
+rooted at~$v$ (including~$v$). Let~$u$ be a child of~$v$, we say the edge~$(v,u)$ is
+\em{heavy} iff $s(u) \ge s(v)/2$, otherwise we say $(v,u)$ is \em{light}. Finally, a
+\em{heavy path} is simply a path containing only heavy edges. 
+}
+
+\obs{
+For any vertex~$v$, there is at most one heavy edge from~$v$ to its children. Therefore,
+each vertex~$v$ lies on exactly one heavy path (the path can consist of only~$v$).
+}
+
+\obs{
+Any root-to-leaf path in~$F$ contains at most $\log n$ light edges.
+}
+
+This gives us the decomposition of the tree into heavy paths that connected via light
+edges. The decomposition can be easily found using depth-first search in
+linear time. 
+
+We represent each heavy path using the range tree structure for static path from the
+previous chapter. The root of each range tree will also store the light edge that leads up
+from the top of the path and connects it with other heavy path. 
+
+\TODO decomposition example
+
+The following lemma gives a recipe on how to evaluate path queries and updates:
+
+\lemma{
+Every path $x\to y$ in~$F$ can be partitioned into $\O(\log n)$ light edges and $\O(\log n)$
+subpaths of heavy paths.
+}
+\proof
+If the path is top-down we have $O(\log n)$ light edges by the previous observation and
+these edges split the path into $O(\log n)$ heavy subpaths. Otherwise, path $x\to y$ can
+be divided into two top-down paths at the lowest common ancestor of $x$ and $y$.
+\qed
+
+Thus, we just partition the query (update) into $\O(\log n)$ queries on heavy paths plus
+light edges. As each subquery can be evaluated in $\O(\log n)$ we get $\O(\log^2 n)$ in
+total.
+
+However, there is a catch. To calculate the partitioning, we need to calculate lowest
+common ancestor of~$x$~and~$y$ ($\LCA(x,y)$).
+
+\TODO
+
+
+\section[linkcut]{Link-cut trees}
+\TODO
+
+
+\section{Application: Faster Dinic's algorithm}
+\TODO
+
+
 \endchapter