Photo URL is broken

I haven't really been writing much since I left grad school, but I figured it would be a shame not to capture this year, even if all I can muster is a brain dump and bulleted lists. It was my first year in NYC after all.

The biggest challenge for me has been finding my voice and asserting myself. The sheer number of people and small amount of space turns everything into a competition here. Upon moving here, I moused about always feeling like I was in everyone's way, but I am slowly learning to exercise my right to take up space. Everyone's attention is being pulled in different directions. Another challenge was having enough self-esteem to handled being constantly ghosted 👻 and not taking it personally.


I am ending the year with my Leetcode rating at 2164. Apparently that makes me top 1.25%. I've been aiming for 2300+, but I admittedly don't work too hard at this. I try my luck at a competition maybe once per week. Let me dump some new algorithms I wrote if I need to reuse them later.

Segment Tree

See 2407. Longest Increasing Subsequence II.

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

class Solution {
  int lengthOfLIS(const std::vector<int>& nums, int k);

namespace {

template <typename T>
struct Max {
  constexpr T operator()(const T& a, const T& b) const {
    return std::max(a, b);

template <typename K, typename V, typename Reducer = Max<V>>
class SegmentTree {
  // Disable default constructor.
  SegmentTree() = delete;
  // Disable copy (and move) semantics.
  SegmentTree(const SegmentTree&) = delete;
  SegmentTree<K, V, Reducer>& operator=(const SegmentTree&) = delete;

  const std::pair<K, K>& segment() const { return segment_; }
  const V& value() const { return value_; }
  const SegmentTree<K, V, Reducer>& left() const { return *left_; }
  const SegmentTree<K, V, Reducer>& right() const { return *right_; }
  void Update(K key, V value) {
    if (key < segment_.first || segment_.second < key) return;
    if (segment_.first == segment_.second) {
      value_ = value;
    left_->Update(key, value);
    right_->Update(key, value);
    value_ = reducer_(left_->value(), right_->value());

  V Query(const std::pair<K, K>& segment, V out_of_range_value) {
    if (segment.second < segment_.first || segment.first > segment_.second)
      return out_of_range_value;
    if (segment.first <= segment_.first && segment_.second <= segment.second) {
      return value();
    if (segment.second <= left_->segment().second)
      return left_->Query(segment, out_of_range_value);
    if (right_->segment().first <= segment.first)
      return right_->Query(segment, out_of_range_value);
    return reducer_(left_->Query(segment, out_of_range_value),
                    right_->Query(segment, out_of_range_value));

  // Makes a segment tree from a range with `value` for leaf nodes.
  template <typename It>
  static std::unique_ptr<SegmentTree<K, V, Reducer>> Make(It begin, It end,
                                                          V value) {
    std::pair<int, int> segment{*begin, *end};
    if (begin == end)
      return std::unique_ptr<SegmentTree<K, V, Reducer>>(
          new SegmentTree<K, V, Reducer>(segment, value));
    const auto mid = begin + (end - begin) / 2;
    std::unique_ptr<SegmentTree<K, V, Reducer>> left =
        SegmentTree<K, V, Reducer>::Make(begin, mid, value);
    std::unique_ptr<SegmentTree<K, V, Reducer>> right =
        SegmentTree<K, V, Reducer>::Make(std::next(mid), end, value);
    return std::unique_ptr<SegmentTree<K, V, Reducer>>(
        new SegmentTree<K, V, Reducer>(segment, std::move(left),

  // Leaf node.
  SegmentTree(std::pair<K, K> segment, V value)
      : segment_(segment), value_(value) {}
  // Internal node.
  SegmentTree(std::pair<K, K> segment,
              std::unique_ptr<SegmentTree<K, V, Reducer>> left,
              std::unique_ptr<SegmentTree<K, V, Reducer>> right)
      : segment_(segment),
        value_(reducer_(left_->value(), right_->value())) {}

  const std::pair<K, K> segment_;
  const std::unique_ptr<SegmentTree<K, V, Reducer>> left_;
  const std::unique_ptr<SegmentTree<K, V, Reducer>> right_;
  const Reducer reducer_;
  V value_;

}  // namespace

int Solution::lengthOfLIS(const std::vector<int>& nums, int k) {
  std::vector<int> sorted_nums = nums;
  std::sort(sorted_nums.begin(), sorted_nums.end());
  sorted_nums.erase(std::unique(sorted_nums.begin(), sorted_nums.end()),
  const std::unique_ptr<SegmentTree<int, int>> tree =
      SegmentTree<int, int>::Make(sorted_nums.begin(), --sorted_nums.end(), 0);
  for (int x : nums)
    tree->Update(x, tree->Query(std::make_pair(x - k, x - 1), 0) + 1);
  return tree->value();

Disjoint Set Forest

See 2421. Number of Good Paths.

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <memory>
#include <numeric>
#include <unordered_map>
#include <vector>

class Solution {
  int numberOfGoodPaths(const std::vector<int>& vals,
                        const std::vector<std::vector<int>>& edges);

namespace phillypham {

class DisjointSetForest {
  explicit DisjointSetForest(size_t size) : parent_(size), rank_(size, 0) {
    std::iota(parent_.begin(), parent_.end(), 0);

  void Union(size_t x, size_t y) {
    auto i = Find(x);
    auto j = Find(y);
    if (i == j) return;
    if (rank_[i] > rank_[j]) {
      parent_[j] = i;
    } else {
      parent_[i] = j;
      if (rank_[i] == rank_[j]) rank_[j] = rank_[j] + 1;

  size_t Find(size_t x) {
    while (parent_[x] != x) {
      auto parent = parent_[x];
      parent_[x] = parent_[parent];
      x = parent;
    return x;

  size_t size() const { return parent_.size(); }

  std::vector<size_t> parent_;
  std::vector<size_t> rank_;

}  // namespace phillypham

int Solution::numberOfGoodPaths(const std::vector<int>& vals,
                                const std::vector<std::vector<int>>& edges) {
  const int n = vals.size();
  std::vector<int> ordered_nodes(n);
  std::iota(ordered_nodes.begin(), ordered_nodes.end(), 0);
  std::sort(ordered_nodes.begin(), ordered_nodes.end(),
            [&vals](int i, int j) -> bool { return vals[i] < vals[j]; });
  std::vector<std::vector<int>> adjacency_list(n);
  for (const auto& edge : edges)
    if (vals[edge[0]] < vals[edge[1]])
  phillypham::DisjointSetForest disjoint_set_forest(n);
  int num_good_paths = 0;
  for (int i = 0; i < n;) {
    const int value = vals[ordered_nodes[i]];
    int j = i;
    for (; j < n && vals[ordered_nodes[j]] == value; ++j)
      for (int k : adjacency_list[ordered_nodes[j]])
        disjoint_set_forest.Union(ordered_nodes[j], k);
    std::unordered_map<int, int> component_sizes;
    for (int k = i; k < j; ++k)
    for (const auto& [_, size] : component_sizes)
      num_good_paths += size * (size + 1) / 2;
    i = j;
  return num_good_paths;


I managed to read 12 books this year. Not too bad. Unfortunately, I didn't manage to capture what I took away in the moment, so I will try to dump it here with a few sentences for each book.

Sex and Vanity by Kevin Kwan

This was a fun novel in the Crazy Rich Asians universe. It's like a modern day society novel with social media. In classic Kevin Kwan style, it's filled with over-the-top descriptions of wealth. While mostly light-hearted and silly, the protagonist grapples with an identity crisis familiar to many Asian Americans.

Yolk by Mary H. K. Choi

This novel centers on two Korean-American sisters coming of age in NYC. They are foils: one went to Columbia and works at a hedge fund and the other studies art and dates losers. Both sisters are rather flawed and unlikeable and antiheroes in some sense. The description of the eating disorder is especially disturbing. Probably the most memorable quote for me was this gem:

Because I'm not built for this. I tried it. I did all that Tinder shit. Raya. Bumble. Whatever the fuck, Hinge. I thought maybe it was a good idea. I've had a girlfriend from the time I was fifteen. It's like in high school, Asian dudes were one thing, but a decade later it's like suddenly we're all hot. It was ridiculous. I felt like such a trope, like one of those tech bros who gets allcut up and gets Lasik and acts like a totally different person.

I've never been so accurately dragged in my life. Actually, who I am kidding, I was never hot enough to be having sex with strangers on dating apps.

House of Sticks by Ly Tran

As a child of Vietnamese war refugees, I thought this would be more relatable. It really wasn't at all, but it was still very good. Ly's family came over in different circumstances than mine and her parents never had the opportunity to get an education. I appreciated the different perspective of her life in Queens versus my Pennsylvania suburb. The complex relationship with her father who clearly suffers from PTSD and never really adjusts to life in America is most interesting. He wants to be a strong patriarchical figure for his family, but ultimately, he ends up alienating and hurting his daughter.

The Sympathizer by Viet Thanh Nguyen

I really enjoyed this piece of historical fiction. I have only really ever learned about the Vietnam war from the American perspective which has either been that it was necessary to stem communism or that it was a tragic mistake that killed millions of Vietnamese. But the narrator remarks:

Now that we are the powerful, we don’t need the French or the Americans to fuck us over. We can fuck ourselves just fine.

His experience of moving to America as an adult is also interesting. I was born here and the primary emotions about Vietnamese for me were shame and embarassement. The narrator arrives as an adult and while he has moments of shame and embarassement, he lets himself feel righteous anger.

I felt the ending and the focus on the idea of nothing captures how powerful and yet empty the ideals of communism and the war are.

The Committed by Viet Thanh Nguyen

The sequel to The Sympathizer takes place in France. I don't know if this novel really touches on any new themes. There is the contrast between the Asians and Arabs? But it is very funny, thrilling, and suspenseful as the narrator has to deal with consequences of his lies. Who doesn't enjoy poking fun at the hypocrisy of the French, too?

A Gentleman in Moscow by Amor Towles

This story is seemingly mundane as it takes place almost entirely in the confines of a hotel. But the Count's humor and descriptions of the dining experiences make this novel great fun. The Count teams up with loveable friends like his lover Anna and the barber to undermine the Bishop and the Party. I enjoyed the history lesson of this tumultuous period in Russia, too.

Being somewhat a student of the Russian greats like Tolstoy and Dostoevsky, I appreciated that he would occasionally make references to that body of work.

...the Russian masters could not compute up with a better plot device than two central characters resolving a matter of conscience by means of pistols at thirty-two paces...

Rules of Civility by Amor Towles

I've always enjoyed fiction from this era via Fitzgerald, Hemingway, and Edith Wharton. The modern take on the American society novel is refreshing. Old New York City and the old courtship rituals never fail to capture my imagination. There seems to be a lot to say about a women's place in society when marrying rich was the only option. The men seem to be yearning for a higher purpose than preserving dynastic wealth, too.

The Lincoln Highway by Amor Towles

A really charming coming of age story, where the imagination of teenage boys is brought to its logical conclusion. There is some story about redemption for past mistakes here. The headstrong Sally who has disgressions about doing thing the hard way and her supposed duty to make herself fit for marriage might be my favorite character, and I wish more was done with her. Abacus Abernathe lectures on the magic of New York City (it's just the right size) and deems this adventure worthy of the legends of the old world like Achilles.

I couldn't help but be touched and feeling like I am in on the joke with references to Chelsea Market (where I work) and characters in his previous novels.

Dune by Frank Herbert

I read this one because of the movie, but I didn't really enjoy it. Science fiction has never been of favorite of mine. I didn't like the messiah narrative and found Paul to be arrogant and unlikeable. But maybe that's the reality of playing politics.

The Left Hand of Darkness by Ursula K. Le Guin

This one was an interesting thought experiment about what would the world be like if we didn't have a concept of sex and gender. It makes you think how we immediately classify everyone we meet into a gender. The protagonist struggles with his need to feel masculine in a population with no concept of masculinity.

Bluebeard by Kurt Vonnegut

Rabo is a cranky old man. I wasn't able to identify any larger themes, but it's funny and Rabo's journey to make a meaningful work of art with soul is interesting itself. Abstract art is just too easy an target with its ridiculousness.

Maybe one useful tidbit is that motivation to write can be found by having an audience.


Somehow, I traveled to countries with breakout World Cup teams.


Honestly, I don't know if I could have found Croatia on the map before I went there. It was surprisingly awesome. A beautiful country with great food. The people were proud and enjoyed opening up and sharing their country with us. I'll be back here to climb sometime, I hope.

Congratulations to them for their World Cup performance and adopting the euro.


I don't know if I really enjoyed this one. There didn't seem to be much to do beyond shopping at the markets and seeing the historical sights. I liked the food, but I wasn't crazy about it.


The Enchantments were just breathtaking. The hike took us over 14 hours. Late in the night, I did begin to wonder if were going to make it, though, but it was worth it.

I also did my first multipitch (3 pitches!), here. Thanks Kyle for leading!

New Comment


No comments have been posted yet. You can be the first!