There is a 1-indexed `8 x 8` chessboard containing `3` pieces.

You are given `6` integers `a`, `b`, `c`, `d`, `e`, and `f` where:

* `(a, b)` denotes the position of the white rook.
* `(c, d)` denotes the position of the white bishop.
* `(e, f)` denotes the position of the black queen.

Given that you can only move the white pieces, return the minimum number of
moves required to capture the black queen.

Note that:

* Rooks can move any number of squares either vertically or horizontally, but cannot jump over other pieces.
* Bishops can move any number of squares diagonally, but cannot jump over other pieces.
* A rook or a bishop can capture the queen if it is located in a square that they can move to.
* The queen does not move.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def minMovesToCaptureTheQueen(self, a: int, b: int, c: int, d: int, e: int, f: int) -> int:
    if a == e:
      if c == a and (b < d < f or b > d > f):
        return 2
      else:
        return 1
    if b == f:
      if d == f and (a < c < e or a > c > e):
        return 2
      else:
        return 1
    if c + d == e + f:
      if a + b == c + d and (c < a < e or c > a > e):
        return 2
      else:
        return 1
    if c - d == e - f:
      if a - b == c - d and (c < a < e or c > a > e):
        return 2
      else:
        return 1
    return 2

class Solution {
  public int minMovesToCaptureTheQueen(int a, int b, int c, int d, int e, int f) {
    // The rook is in the same row as the queen.
    if (a == e)
      // The bishop blocks the rook or not.
      return (c == a && (b < d && d < f || b > d && d > f)) ? 2 : 1;
    // The rook is in the same column as the queen.
    if (b == f)
      // The bishop blocks the rook or not.
      return (d == f && (a < c && c < e || a > c && c > e)) ? 2 : 1;
    // The bishop is in the same up-diagonal as the queen.
    if (c + d == e + f)
      // The rook blocks the bishop or not.
      return (a + b == c + d && (c < a && a < e || c > a && a > e)) ? 2 : 1;
    // The bishop is in the same down-diagonal as the queen.
    if (c - d == e - f)
      // The rook blocks the bishop or not.
      return (a - b == c - d && (c < a && a < e || c > a && a > e)) ? 2 : 1;
    // The rook can always get the green in two steps.
    return 2;
  }
}

class Solution {
 public:
  int minMovesToCaptureTheQueen(int a, int b, int c, int d, int e, int f) {
    // The rook is in the same row as the queen.
    if (a == e)
      // The bishop blocks the rook or not.
      return (c == a && (b < d && d < f || b > d && d > f)) ? 2 : 1;
    // The rook is in the same column as the queen.
    if (b == f)
      // The bishop blocks the rook or not.
      return (d == f && (a < c && c < e || a > c && c > e)) ? 2 : 1;
    // The bishop is in the same up-diagonal as the queen.
    if (c + d == e + f)
      // The rook blocks the bishop or not.
      return (a + b == c + d && (c < a && a < e || c > a && a > e)) ? 2 : 1;
    // The bishop is in the same down-diagonal as the queen.
    if (c - d == e - f)
      // The rook blocks the bishop or not.
      return (a - b == c - d && (c < a && a < e || c > a && a > e)) ? 2 : 1;
    // The rook can always get the green in two steps.
    return 2;
  }
};


Find Beautiful Indices in the Given Array I

You are given a 0-indexed string `s`, a string `a`, a string `b`, and an
integer `k`.

An index `i` is beautiful if:

* `0 <= i <= s.length - a.length`
* `s[i..(i + a.length - 1)] == a`
* There exists an index `j` such that:
* `0 <= j <= s.length - b.length`
* `s[j..(j + b.length - 1)] == b`
* `|j - i| <= k`

Return the array that contains beautiful indices in sorted order from smallest
to largest.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def beautifulIndices(self, s: str, a: str, b: str, k: int) -> List[int]:
    ans = []
    indicesA = self._kmp(s, a)
    indicesB = self._kmp(s, b)
    indicesBIndex = 0

    for i in indicesA:
      while indicesBIndex < len(indicesB) and indicesB[indicesBIndex] - i < -k:
        indicesBIndex += 1
      if indicesBIndex < len(indicesB) and indicesB[indicesBIndex] - i <= k:
        ans.append(i)

    return ans

  def _kmp(self, s: str, pattern: str) -> List[int]:
    def getLPS(pattern: str) -> List[int]:
      lps = [0] * len(pattern)
      j = 0
      for i in range(1, len(pattern)):
        while j > 0 and pattern[j] != pattern[i]:
          j = lps[j - 1]
        if pattern[i] == pattern[j]:
          lps[i] = j + 1
          j += 1
      return lps

    res = []
    lps = getLPS(pattern)
    i = 0
    j = 0
    while i < len(s):
      if s[i] == pattern[j]:
        i += 1
        j += 1
        if j == len(pattern):
          res.append(i - j)
          j = lps[j - 1]
      elif j != 0:
        j = lps[j - 1]
      else:
        i += 1
    return res

class Solution {
  public List<Integer> beautifulIndices(String s, String a, String b, int k) {
    List<Integer> ans = new ArrayList<>();
    List<Integer> indicesA = kmp(s, a);
    List<Integer> indicesB = kmp(s, b);
    int indicesBIndex = 0; // indicesB' index

    for (final int i : indicesA) {
      // The constraint is: |j - i| <= k. So, -k <= j - i <= k. So, move
      // `indicesBIndex` s.t. j - i >= -k, where j := indicesB[indicesBIndex].
      while (indicesBIndex < indicesB.size() && indicesB.get(indicesBIndex) - i < -k)
        ++indicesBIndex;
      if (indicesBIndex < indicesB.size() && indicesB.get(indicesBIndex) - i <= k)
        ans.add(i);
    }

    return ans;
  }

  // Returns the starting indices of all occurrences of the pattern in `s`.
  private List<Integer> kmp(final String s, final String pattern) {
    List<Integer> res = new ArrayList<>();
    int[] lps = getLPS(pattern);
    int i = 0; // s' index
    int j = 0; // pattern's index
    while (i < s.length()) {
      if (s.charAt(i) == pattern.charAt(j)) {
        ++i;
        ++j;
        if (j == pattern.length()) {
          res.add(i - j);
          j = lps[j - 1];
        }
      } else if (j != 0) { // Mismatch after j matches.
        // Don't match lps[0..lps[j - 1]] since they will match anyway.
        j = lps[j - 1];
      } else {
        ++i;
      }
    }
    return res;
  }

  // Returns the lps array, where lps[i] is the length of the longest prefix of
  // pattern[0..i] which is also a suffix of this substring.
  private int[] getLPS(final String pattern) {
    int[] lps = new int[pattern.length()];
    for (int i = 1, j = 0; i < pattern.length(); ++i) {
      while (j > 0 && pattern.charAt(j) != pattern.charAt(i))
        j = lps[j - 1];
      if (pattern.charAt(i) == pattern.charAt(j))
        lps[i] = ++j;
    }
    return lps;
  }
}

class Solution {
 public:
  vector<int> beautifulIndices(string s, string a, string b, int k) {
    vector<int> ans;
    const vector<int> indicesA = kmp(s, a);
    const vector<int> indicesB = kmp(s, b);
    int indicesBIndex = 0;  // indicesB's index

    for (const int i : indicesA) {
      // The constraint is: |j - i| <= k. So, -k <= j - i <= k. So, move
      // `indicesBIndex` s.t. j - i >= -k, where j := indicesB[indicesBIndex].
      while (indicesBIndex < indicesB.size() &&
             indicesB[indicesBIndex] - i < -k)
        ++indicesBIndex;
      if (indicesBIndex < indicesB.size() && indicesB[indicesBIndex] - i <= k)
        ans.push_back(i);
    }

    return ans;
  }

 private:
  // Returns the starting indices of all occurrences of the pattern in `s`.
  vector<int> kmp(const string& s, const string& pattern) {
    vector<int> res;
    const vector<int> lps = getLPS(pattern);
    int i = 0;  // s' index
    int j = 0;  // pattern's index
    while (i < s.length()) {
      if (s[i] == pattern[j]) {
        ++i;
        ++j;
        if (j == pattern.length()) {
          res.push_back(i - j);
          j = lps[j - 1];
        }
      } else if (j > 0) {  // Mismatch after j matches.
        // Don't match lps[0..lps[j - 1]] since they will match anyway.
        j = lps[j - 1];
      } else {
        ++i;
      }
    }
    return res;
  }

  // Returns the lps array, where lps[i] is the length of the longest prefix of
  // pattern[0..i] which is also a suffix of this substring.
  vector<int> getLPS(const string& pattern) {
    vector<int> lps(pattern.length());
    for (int i = 1, j = 0; i < pattern.length(); ++i) {
      while (j > 0 && pattern[j] != pattern[i])
        j = lps[j - 1];
      if (pattern[i] == pattern[j])
        lps[i] = ++j;
    }
    return lps;
  }
};


You are given a 0-indexed string `word` and an integer `k`.

At every second, you must perform the following operations:

* Remove the first `k` characters of `word`.
* Add any `k` characters to the end of `word`.

Note that you do not necessarily need to add the same characters that you
removed. However, you must perform both operations at every second.

Return the minimum time greater than zero required for `word` to revert to its
initial state.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def minimumTimeToInitialState(self, word: str, k: int) -> int:
    n = len(word)
    maxOps = (n - 1) // k + 1
    z = self._zFunction(word)

    for ans in range(1, maxOps):
      if z[ans * k] >= n - ans * k:
        return ans

    return maxOps

  def _zFunction(self, s: str) -> List[int]:
    n = len(s)
    z = [0] * n
    l = 0
    r = 0
    for i in range(1, n):
      if i < r:
        z[i] = min(r - i, z[i - l])
      while i + z[i] < n and s[z[i]] == s[i + z[i]]:
        z[i] += 1
      if i + z[i] > r:
        l = i
        r = i + z[i]
    return z

class Solution {
  // Same as 3029. Minimum Time to Revert Word to Initial State I
  public int minimumTimeToInitialState(String word, int k) {
    final int n = word.length();
    final int maxOps = (n - 1) / k + 1;
    final int[] z = zFunction(word);
    for (int ans = 1; ans < maxOps; ++ans)
      if (z[ans * k] >= n - ans * k)
        return ans;
    return maxOps;
  }

  // Returns the z array, where z[i] is the length of the longest prefix of
  // s[i..n) which is also a prefix of s.
  //
  // https://cp-algorithms.com/string/z-function.html#implementation
  private int[] zFunction(final String s) {
    final int n = s.length();
    int[] z = new int[n];
    int l = 0;
    int r = 0;
    for (int i = 1; i < n; ++i) {
      if (i < r)
        z[i] = Math.min(r - i, z[i - l]);
      while (i + z[i] < n && s.charAt(z[i]) == s.charAt(i + z[i]))
        ++z[i];
      if (i + z[i] > r) {
        l = i;
        r = i + z[i];
      }
    }
    return z;
  }
}

class Solution {
 public:
  // Same as 3029. Minimum Time to Revert Word to Initial State I
  int minimumTimeToInitialState(string word, int k) {
    const int n = word.length();
    const int maxOps = (n - 1) / k + 1;
    const vector<int> z = zFunction(word);
    for (int ans = 1; ans < maxOps; ++ans)
      if (z[ans * k] >= n - ans * k)
        return ans;
    return maxOps;
  }

  // Returns the z array, where z[i] is the length of the longest prefix of
  // s[i..n) which is also a prefix of s.
  //
  // https://cp-algorithms.com/string/z-function.html#implementation
  vector<int> zFunction(const string& s) {
    const int n = s.length();
    vector<int> z(n);
    int l = 0;
    int r = 0;
    for (int i = 1; i < n; ++i) {
      if (i < r)
        z[i] = min(r - i, z[i - l]);
      while (i + z[i] < n && s[z[i]] == s[i + z[i]])
        ++z[i];
      if (i + z[i] > r) {
        l = i;
        r = i + z[i];
      }
    }
    return z;
  }
};


You are given a 0-indexed `m x n` grid `image` which represents a grayscale
image, where `image[i][j]` represents a pixel with intensity in the
range`[0..255]`. You are also given a non-negative integer `threshold`.

Two pixels `image[a][b]` and `image[c][d]` are said to be adjacent if `|a - c|
+ |b - d| == 1`.

A region is a `3 x 3` subgrid where the absolute difference in intensity
between any two adjacent pixels is less than or equal to `threshold`.

All pixels in a region belong to that region, note that a pixel can belong to
multiple regions.

You need to calculate a 0-indexed `m x n` grid `result`, where `result[i][j]`
is the average intensity of the region to which `image[i][j]` belongs, rounded
down to the nearest integer. If `image[i][j]` belongs to multiple regions,
`result[i][j]` is the average of the rounded down average intensities of these
regions, rounded down to the nearest integer. If `image[i][j]` does not belong
to any region, `result[i][j]` is equal to `image[i][j]`.

Return the grid `result`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def resultGrid(self, image: List[List[int]], threshold: int) -> List[List[int]]:
    m = len(image)
    n = len(image[0])
    sums = [[0] * n for _ in range(m)]
    counts = [[0] * n for _ in range(m)]

    for i in range(m - 2):
      for j in range(n - 2):
        if self._isRegion(image, i, j, threshold):
          subgridSum = sum(image[x][y] for x in range(i, i + 3) for y in range(j, j + 3))
          for x in range(i, i + 3):
            for y in range(j, j + 3):
              sums[x][y] += subgridSum // 9
              counts[x][y] += 1

    for i in range(m):
      for j in range(n):
        if counts[i][j] > 0:
          image[i][j] = sums[i][j] // counts[i][j]

    return image

  def _isRegion(self, image: List[List[int]], i: int, j: int, threshold: int) -> bool:
    for x in range(i, i + 3):
      for y in range(j, j + 3):
        if x > i and abs(image[x][y] - image[x - 1][y]) > threshold:
          return False
        if y > j and abs(image[x][y] - image[x][y - 1]) > threshold:
          return False
    return True

class Solution {
  public int[][] resultGrid(int[][] image, int threshold) {
    final int m = image.length;
    final int n = image[0].length;
    int[][] sums = new int[m][n];
    int[][] counts = new int[m][n];

    for (int i = 0; i < m - 2; ++i)
      for (int j = 0; j < n - 2; ++j)
        if (isRegion(image, i, j, threshold)) {
          final int subgridSum = getSubgridSum(image, i, j);
          for (int x = i; x < i + 3; ++x)
            for (int y = j; y < j + 3; ++y) {
              sums[x][y] += subgridSum / 9;
              counts[x][y] += 1;
            }
        }

    for (int i = 0; i < m; ++i)
      for (int j = 0; j < n; ++j)
        if (counts[i][j] > 0)
          image[i][j] = sums[i][j] / counts[i][j];

    return image;
  }

  // Returns true if image[i..i + 2][j..j + 2] is a region.
  private boolean isRegion(int[][] image, int i, int j, int threshold) {
    for (int x = i; x < i + 3; ++x)
      for (int y = j; y < j + 3; ++y) {
        if (x > i && Math.abs(image[x][y] - image[x - 1][y]) > threshold)
          return false;
        if (y > j && Math.abs(image[x][y] - image[x][y - 1]) > threshold)
          return false;
      }
    return true;
  }

  // Returns the sum of image[i..i + 2][j..j + 2].
  private int getSubgridSum(int[][] image, int i, int j) {
    int subgridSum = 0;
    for (int x = i; x < i + 3; ++x)
      for (int y = j; y < j + 3; ++y)
        subgridSum += image[x][y];
    return subgridSum;
  }
}

class Solution {
 public:
  vector<vector<int>> resultGrid(vector<vector<int>>& image, int threshold) {
    const int m = image.size();
    const int n = image[0].size();
    vector<vector<int>> sums(m, vector<int>(n));
    vector<vector<int>> counts(m, vector<int>(n));

    for (int i = 0; i < m - 2; ++i)
      for (int j = 0; j < n - 2; ++j)
        if (isRegion(image, i, j, threshold)) {
          const int subgridSum = getSubgridSum(image, i, j);
          for (int x = i; x < i + 3; ++x)
            for (int y = j; y < j + 3; ++y) {
              sums[x][y] += subgridSum / 9;
              counts[x][y] += 1;
            }
        }

    for (int i = 0; i < m; ++i)
      for (int j = 0; j < n; ++j)
        if (counts[i][j] > 0)
          image[i][j] = sums[i][j] / counts[i][j];

    return image;
  }

 private:
  // Returns true if image[i..i + 2][j..j + 2] is a region.
  bool isRegion(const vector<vector<int>>& image, int i, int j, int threshold) {
    for (int x = i; x < i + 3; ++x)
      for (int y = j; y < j + 3; ++y) {
        if (x > i && abs(image[x][y] - image[x - 1][y]) > threshold)
          return false;
        if (y > j && abs(image[x][y] - image[x][y - 1]) > threshold)
          return false;
      }
    return true;
  }

  // Returns the sum of image[i..i + 2][j..j + 2].
  int getSubgridSum(const vector<vector<int>>& image, int i, int j) {
    int subgridSum = 0;
    for (int x = i; x < i + 3; ++x)
      for (int y = j; y < j + 3; ++y)
        subgridSum += image[x][y];
    return subgridSum;
  }
};


Find the Length of the Longest Common Prefix

You are given two arrays with positive integers `arr1` and `arr2`.

A prefix of a positive integer is an integer formed by one or more of its
digits, starting from its leftmost digit. For example, `123` is a prefix of
the integer `12345`, while `234` is not.

A common prefix of two integers `a` and `b` is an integer `c`, such that `c`
is a prefix of both `a` and `b`. For example, `5655359` and `56554` have a
common prefix `565` while `1223` and `43456` do not have a common prefix.

You need to find the length of the longest common prefix between all pairs of
integers `(x, y)` such that `x` belongs to `arr1` and `y` belongs to `arr2`.

Return the length of the longest common prefix among all pairs. If no common
prefix exists among them, return `0`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class TrieNode:
  def __init__(self):
    self.children: Dict[str, TrieNode] = {}

class Trie:
  def __init__(self):
    self.root = TrieNode()

  def insert(self, word: str) -> None:
    node: TrieNode = self.root
    for c in word:
      node = node.children.setdefault(c, TrieNode())
    node.isWord = True

  def search(self, word: str) -> int:
    prefixLength = 0
    node = self.root
    for c in word:
      if c not in node.children:
        break
      node = node.children[c]
      prefixLength += 1
    return prefixLength

class Solution:
  def longestCommonPrefix(self, arr1: List[int], arr2: List[int]) -> int:
    trie = Trie()

    for num in arr1:
      trie.insert(str(num))

    return max(trie.search(str(num)) for num in arr2)

class TrieNode {
  public TrieNode[] children = new TrieNode[10];
}

class Trie {
  public void insert(final String word) {
    TrieNode node = root;
    for (final char c : word.toCharArray()) {
      final int i = c - '0';
      if (node.children[i] == null)
        node.children[i] = new TrieNode();
      node = node.children[i];
    }
  }

  public int search(final String word) {
    int prefixLength = 0;
    TrieNode node = root;
    for (final char c : word.toCharArray()) {
      final int i = c - '0';
      if (node.children[i] == null)
        break;
      node = node.children[i];
      ++prefixLength;
    }
    return prefixLength;
  }

  private TrieNode root = new TrieNode();
}

class Solution {
  public int longestCommonPrefix(int[] arr1, int[] arr2) {
    int ans = 0;
    Trie trie = new Trie();

    for (final int num : arr1)
      trie.insert(Integer.toString(num));

    for (final int num : arr2)
      ans = Math.max(ans, trie.search(Integer.toString(num)));

    return ans;
  }
}

struct TrieNode {
  vector<shared_ptr<TrieNode>> children;
  TrieNode() : children(10) {}
};

class Trie {
 public:
  void insert(const string& word) {
    shared_ptr<TrieNode> node = root;
    for (const char c : word) {
      const int i = c - '0';
      if (node->children[i] == nullptr)
        node->children[i] = make_shared<TrieNode>();
      node = node->children[i];
    }
  }

  int search(const string& word) {
    int prefixLength = 0;
    shared_ptr<TrieNode> node = root;
    for (const char c : word) {
      const int i = c - '0';
      if (node->children[i] == nullptr)
        break;
      node = node->children[i];
      ++prefixLength;
    }
    return prefixLength;
  }

 private:
  shared_ptr<TrieNode> root = make_shared<TrieNode>();
};

class Solution {
 public:
  int longestCommonPrefix(vector<int>& arr1, vector<int>& arr2) {
    int ans = 0;
    Trie trie;

    for (const int num : arr1)
      trie.insert(to_string(num));

    for (const int num : arr2)
      ans = max(ans, trie.search(to_string(num)));

    return ans;
  }
};


You are given a `m x n` 0-indexed 2D matrix `mat`. From every cell, you can
create numbers in the following way:

* There could be at most `8` paths from the cells namely: east, south-east, south, south-west, west, north-west, north, and north-east.
* Select a path from them and append digits in this path to the number being formed by traveling in this direction.
* Note that numbers are generated at every step, for example, if the digits along the path are `1, 9, 1`, then there will be three numbers generated along the way: `1, 19, 191`.

Return the most frequent prime number greater than `10` out of all the numbers
created by traversing the matrix or `-1` if no such prime number exists. If
there are multiple prime numbers with the highest frequency, then return the
largest among them.

Note: It is invalid to change the direction during the move.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def mostFrequentPrime(self, mat: List[List[int]]) -> int:
    dirs = ((1, 0), (1, -1), (0, -1), (-1, -1),
            (-1, 0), (-1, 1), (0, 1), (1, 1))
    m = len(mat)
    n = len(mat[0])
    count = collections.Counter()

    def isPrime(num: int) -> bool:
      return not any(num % i == 0 for i in range(2, int(num**0.5 + 1)))

    for i in range(m):
      for j in range(n):
        for dx, dy in dirs:
          num = 0
          x = i
          y = j
          while 0 <= x < m and 0 <= y < n:
            num = num * 10 + mat[x][y]
            if num > 10 and isPrime(num):
              count[num] += 1
            x += dx
            y += dy

    if not count.items():
      return -1
    return max(count.items(), key=lambda x: (x[1], x[0]))[0]

class Solution {
  public int mostFrequentPrime(int[][] mat) {
    final int[][] DIRS = {{1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1}};
    final int m = mat.length;
    final int n = mat[0].length;
    int ans = -1;
    int maxFreq = 0;
    Map<Integer, Integer> count = new HashMap<>();

    for (int i = 0; i < m; ++i)
      for (int j = 0; j < n; ++j)
        for (int[] dir : DIRS) {
          int num = 0;
          int x = i;
          int y = j;
          while (0 <= x && x < m && 0 <= y && y < n) {
            num = num * 10 + mat[x][y];
            if (num > 10 && isPrime(num))
              count.merge(num, 1, Integer::sum);
            x += dir[0];
            y += dir[1];
          }
        }

    for (Map.Entry<Integer, Integer> entry : count.entrySet()) {
      final int prime = entry.getKey();
      final int freq = entry.getValue();
      if (freq > maxFreq) {
        ans = prime;
        maxFreq = freq;
      } else if (freq == maxFreq) {
        ans = Math.max(ans, prime);
      }
    }

    return ans;
  }

  private boolean isPrime(int num) {
    for (int i = 2; i < (int) Math.sqrt(num) + 1; ++i)
      if (num % i == 0)
        return false;
    return true;
  }
}

class Solution {
 public:
  int mostFrequentPrime(vector<vector<int>>& mat) {
    constexpr int kDirs[8][2] = {{1, 0},  {1, -1}, {0, -1}, {-1, -1},
                                 {-1, 0}, {-1, 1}, {0, 1},  {1, 1}};
    const int m = mat.size();
    const int n = mat[0].size();
    int ans = -1;
    int maxFreq = 0;
    unordered_map<int, int> count;

    for (int i = 0; i < m; ++i)
      for (int j = 0; j < n; ++j)
        for (const auto& [dx, dy] : kDirs) {
          int num = 0;
          for (int x = i, y = j; 0 <= x && x < m && 0 <= y && y < n;
               x += dx, y += dy) {
            num = num * 10 + mat[x][y];
            if (num > 10 && isPrime(num))
              ++count[num];
          }
        }

    for (const auto& [prime, freq] : count)
      if (freq > maxFreq) {
        ans = prime;
        maxFreq = freq;
      } else if (freq == maxFreq) {
        ans = max(ans, prime);
      }

    return ans;
  }

 private:
  bool isPrime(int num) {
    for (int i = 2; i < sqrt(num) + 1; ++i)
      if (num % i == 0)
        return false;
    return true;
  }
};


You are given a 1-indexed array of integers `nums` of length `n`.

We define a function `greaterCount` such that `greaterCount(arr, val)` returns
the number of elements in `arr` that are strictly greater than `val`.

You need to distribute all the elements of `nums` between two arrays `arr1`
and `arr2` using `n` operations. In the first operation, append `nums[1]` to
`arr1`. In the second operation, append `nums[2]` to `arr2`. Afterwards, in
the `ith` operation:

* If `greaterCount(arr1, nums[i]) > greaterCount(arr2, nums[i])`, append `nums[i]` to `arr1`.
* If `greaterCount(arr1, nums[i]) < greaterCount(arr2, nums[i])`, append `nums[i]` to `arr2`.
* If `greaterCount(arr1, nums[i]) == greaterCount(arr2, nums[i])`, append `nums[i]` to the array with a lesser number of elements.
* If there is still a tie, append `nums[i]` to `arr1`.

The array `result` is formed by concatenating the arrays `arr1` and `arr2`.
For example, if `arr1 == [1,2,3]` and `arr2 == [4,5,6]`, then `result =
[1,2,3,4,5,6]`.

Return the integer array `result`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class FenwickTree:
  def __init__(self, n: int):
    self.sums = [0] * (n + 1)

  def update(self, i: int, delta: int) -> None:
    while i < len(self.sums):
      self.sums[i] += delta
      i += FenwickTree.lowbit(i)

  def get(self, i: int) -> int:
    summ = 0
    while i > 0:
      summ += self.sums[i]
      i -= FenwickTree.lowbit(i)
    return summ

  @staticmethod
  def lowbit(i: int) -> int:
    return i & -i

class Solution:
  def resultArray(self, nums: List[int]) -> List[int]:
    arr1 = []
    arr2 = []
    ranks = self._getRanks(nums)
    tree1 = FenwickTree(len(ranks))
    tree2 = FenwickTree(len(ranks))

    def add(num: int, arr: List[int], tree: FenwickTree) -> None:
      arr.append(num)
      tree.update(ranks[num], 1)

    add(nums[0], arr1, tree1)
    add(nums[1], arr2, tree2)

    for i in range(2, len(nums)):
      greaterCount1 = len(arr1) - tree1.get(ranks[nums[i]])
      greaterCount2 = len(arr2) - tree2.get(ranks[nums[i]])
      if greaterCount1 > greaterCount2:
        add(nums[i], arr1, tree1)
      elif greaterCount1 < greaterCount2:
        add(nums[i], arr2, tree2)
      elif len(arr1) > len(arr2):
        add(nums[i], arr2, tree2)
      else:
        add(nums[i], arr1, tree1)

    return arr1 + arr2

  def _getRanks(self, nums: List[int]) -> Dict[int, int]:
    ranks = collections.Counter()
    rank = 0
    for num in sorted(set(nums)):
      rank += 1
      ranks[num] = rank
    return ranks

class FenwickTree {
  public FenwickTree(int n) {
    sums = new int[n + 1];
  }

  public void add(int i, int delta) {
    while (i < sums.length) {
      sums[i] += delta;
      i += lowbit(i);
    }
  }

  public int get(int i) {
    int sum = 0;
    while (i > 0) {
      sum += sums[i];
      i -= lowbit(i);
    }
    return sum;
  }

  private int[] sums;

  private static int lowbit(int i) {
    return i & -i;
  }
}

class Solution {
  public int[] resultArray(int[] nums) {
    List<Integer> arr1 = new ArrayList<>();
    List<Integer> arr2 = new ArrayList<>();
    Map<Integer, Integer> ranks = getRanks(nums);
    FenwickTree tree1 = new FenwickTree(ranks.size());
    FenwickTree tree2 = new FenwickTree(ranks.size());

    add(nums[0], arr1, tree1, ranks);
    add(nums[1], arr2, tree2, ranks);

    for (int i = 2; i < nums.length; ++i) {
      final int greaterCount1 = arr1.size() - tree1.get(ranks.get(nums[i]));
      final int greaterCount2 = arr2.size() - tree2.get(ranks.get(nums[i]));
      if (greaterCount1 > greaterCount2)
        add(nums[i], arr1, tree1, ranks);
      else if (greaterCount1 < greaterCount2)
        add(nums[i], arr2, tree2, ranks);
      else if (arr1.size() > arr2.size())
        add(nums[i], arr2, tree2, ranks);
      else
        add(nums[i], arr1, tree1, ranks);
    }

    arr1.addAll(arr2);
    return arr1.stream().mapToInt(Integer::intValue).toArray();
  }

  private Map<Integer, Integer> getRanks(int[] nums) {
    Map<Integer, Integer> ranks = new HashMap<>();
    SortedSet<Integer> sorted = new TreeSet<>();
    for (final int num : nums)
      sorted.add(num);
    int rank = 0;
    for (Iterator<Integer> it = sorted.iterator(); it.hasNext();)
      ranks.put(it.next(), ++rank);
    return ranks;
  }

  private void add(int num, List<Integer> arr, FenwickTree tree, Map<Integer, Integer> ranks) {
    arr.add(num);
    tree.add(ranks.get(num), 1);
  };
}

class FenwickTree {
 public:
  FenwickTree(int n) : sums(n + 1) {}

  void add(int i, int delta) {
    while (i < sums.size()) {
      sums[i] += delta;
      i += lowbit(i);
    }
  }

  int get(int i) const {
    int sum = 0;
    while (i > 0) {
      sum += sums[i];
      i -= lowbit(i);
    }
    return sum;
  }

 private:
  vector<int> sums;

  static inline int lowbit(int i) {
    return i & -i;
  }
};

class Solution {
 public:
  vector<int> resultArray(vector<int>& nums) {
    vector<int> arr1;
    vector<int> arr2;
    const unordered_map<int, int> ranks = getRanks(nums);
    FenwickTree tree1(ranks.size());
    FenwickTree tree2(ranks.size());

    add(nums[0], arr1, tree1, ranks);
    add(nums[1], arr2, tree2, ranks);

    for (int i = 2; i < nums.size(); ++i) {
      const int greaterCount1 = arr1.size() - tree1.get(ranks.at(nums[i]));
      const int greaterCount2 = arr2.size() - tree2.get(ranks.at(nums[i]));
      if (greaterCount1 > greaterCount2)
        add(nums[i], arr1, tree1, ranks);
      else if (greaterCount1 < greaterCount2)
        add(nums[i], arr2, tree2, ranks);
      else if (arr1.size() > arr2.size())
        add(nums[i], arr2, tree2, ranks);
      else
        add(nums[i], arr1, tree1, ranks);
    }

    arr1.insert(arr1.end(), arr2.begin(), arr2.end());
    return arr1;
  }

 private:
  unordered_map<int, int> getRanks(const vector<int>& nums) {
    unordered_map<int, int> ranks;
    set<int> sorted(nums.begin(), nums.end());
    int rank = 0;
    for (const int num : sorted)
      ranks[num] = ++rank;
    return ranks;
  }

  void add(int num, vector<int>& arr, FenwickTree& tree,
           const unordered_map<int, int>& ranks) {
    arr.push_back(num);
    tree.add(ranks.at(num), 1);
  };
};


You are given an array `nums` of non-negative integers and an integer `k`.

An array is called special if the bitwise `OR` of all of its elements is at
least `k`.

Return the length of the shortest special non-empty subarray of `nums`, or
return `-1` if no special subarray exists.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def minimumSubarrayLength(self, nums: List[int], k: int) -> int:
    ans = len(nums) + 1
    ors = 0
    count = collections.Counter()

    l = 0
    for r, num in enumerate(nums):
      ors = self._orNum(ors, num, count)
      while ors >= k and l <= r:
        ans = min(ans, r - l + 1)
        ors = self._undoOrNum(ors, nums[l], count)
        l += 1

    return -1 if ans == len(nums) + 1 else ans

  def _orNum(self, ors: int, num: int, count: Dict[int, int]) -> int:
    for i in range(30):
      if num >> i & 1:
        count[i] += 1
        if count[i] == 1:
          ors += 1 << i
    return ors

  def _undoOrNum(self, ors: int, num: int, count: Dict[int, int]) -> int:
    for i in range(30):
      if num >> i & 1:
        count[i] -= 1
        if count[i] == 0:
          ors -= 1 << i
    return ors

class Solution {
  public int minimumSubarrayLength(int[] nums, int k) {
    final int MAX = 50;
    final int n = nums.length;
    int ans = n + 1;
    int ors = 0;
    int[] count = new int[MAX + 1];

    for (int l = 0, r = 0; r < n; ++r) {
      ors = orNum(ors, nums[r], count);
      while (ors >= k && l <= r) {
        ans = Math.min(ans, r - l + 1);
        ors = undoOrNum(ors, nums[l], count);
        ++l;
      }
    }

    return (ans == n + 1) ? -1 : ans;
  }

  private static final int MAX_BIT = 30;

  private int orNum(int ors, int num, int[] count) {
    for (int i = 0; i < MAX_BIT; ++i)
      if ((num >> i & 1) == 1 && ++count[i] == 1)
        ors += 1 << i;
    return ors;
  }

  private int undoOrNum(int ors, int num, int[] count) {
    for (int i = 0; i < MAX_BIT; ++i)
      if ((num >> i & 1) == 1 && --count[i] == 0)
        ors -= 1 << i;
    return ors;
  }
}

class Solution {
 public:
  int minimumSubarrayLength(vector<int>& nums, int k) {
    constexpr int kMax = 50;
    const int n = nums.size();
    int ans = n + 1;
    int ors = 0;
    vector<int> count(kMax + 1);

    for (int l = 0, r = 0; r < n; r++) {
      ors = orNum(ors, nums[r], count);
      while (ors >= k && l <= r) {
        ans = min(ans, r - l + 1);
        ors = undoOrNum(ors, nums[l], count);
        ++l;
      }
    }

    return (ans == n + 1) ? -1 : ans;
  }

 private:
  static constexpr int kMaxBit = 30;

  int orNum(int ors, int num, vector<int>& count) {
    for (int i = 0; i < kMaxBit; ++i)
      if (num >> i & 1 && ++count[i] == 1)
        ors += 1 << i;
    return ors;
  }

  int undoOrNum(int ors, int num, vector<int>& count) {
    for (int i = 0; i < kMaxBit; ++i)
      if (num >> i & 1 && --count[i] == 0)
        ors -= 1 << i;
    return ors;
  }
};


You are given a array `points` representing integer coordinates of some points
on a 2D plane, where `points[i] = [xi, yi]`.

The distance between two points is defined as their Manhattan distance.

Return the minimum possible value for maximum distance between any two points
by removing exactly one point.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def minimumDistance(self, points: List[List[int]]) -> int:
    i, j = self._maxManhattanDistance(points, -1)
    xi, yi = self._maxManhattanDistance(points, i)
    xj, yj = self._maxManhattanDistance(points, j)
    return min(self._manhattan(points, xi, yi), self._manhattan(points, xj, yj))

  def _maxManhattanDistance(self, points: List[List[int]], excludedIndex: int) -> int:
    minSum = math.inf
    maxSum = -math.inf
    minDiff = math.inf
    maxDiff = -math.inf
    minSumIndex = -1
    maxSumIndex = -1
    minDiffIndex = -1
    maxDiffIndex = -1

    for i, (x, y) in enumerate(points):
      if i == excludedIndex:
        continue
      summ = x + y
      diff = x - y
      if summ < minSum:
        minSum = summ
        minSumIndex = i
      if summ > maxSum:
        maxSum = summ
        maxSumIndex = i
      if diff < minDiff:
        minDiff = diff
        minDiffIndex = i
      if diff > maxDiff:
        maxDiff = diff
        maxDiffIndex = i

    if maxSum - minSum >= maxDiff - minDiff:
      return [minSumIndex, maxSumIndex]
    else:
      return [minDiffIndex, maxDiffIndex]

  def _manhattan(self, points: List[List[int]], i: int, j: int) -> int:
    return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])

class Solution {
  public int minimumDistance(int[][] points) {
    final int[] maxIndices = maxManhattanDistance(points, -1);
    final int[] xiyi = maxManhattanDistance(points, maxIndices[0]);
    final int[] xjyj = maxManhattanDistance(points, maxIndices[1]);
    return Math.min(manhattan(points, xiyi[0], xiyi[1]), //
                    manhattan(points, xjyj[0], xjyj[1]));
  }

  // Returns the pair of indices a and b where points[a] and points[b] have the
  // maximum Manhattan distance and a != excludedIndex and b != excludedIndex.
  private int[] maxManhattanDistance(int[][] points, int excludedIndex) {
    int minSum = Integer.MAX_VALUE;
    int maxSum = Integer.MIN_VALUE;
    int minDiff = Integer.MAX_VALUE;
    int maxDiff = Integer.MIN_VALUE;
    int minSumIndex = -1;
    int maxSumIndex = -1;
    int minDiffIndex = -1;
    int maxDiffIndex = -1;

    for (int i = 0; i < points.length; ++i) {
      if (i == excludedIndex)
        continue;
      final int x = points[i][0];
      final int y = points[i][1];
      final int sum = x + y;
      final int diff = x - y;
      if (sum < minSum) {
        minSum = sum;
        minSumIndex = i;
      }
      if (sum > maxSum) {
        maxSum = sum;
        maxSumIndex = i;
      }
      if (diff < minDiff) {
        minDiff = diff;
        minDiffIndex = i;
      }
      if (diff > maxDiff) {
        maxDiff = diff;
        maxDiffIndex = i;
      }
    }

    return maxSum - minSum >= maxDiff - minDiff ? new int[] {minSumIndex, maxSumIndex}
                                                : new int[] {minDiffIndex, maxDiffIndex};
  }

  private int manhattan(int[][] points, int i, int j) {
    return Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);
  }
}

class Solution {
 public:
  int minimumDistance(vector<vector<int>>& points) {
    const auto [i, j] = maxManhattanDistance(points, -1);
    const auto [xi, yi] = maxManhattanDistance(points, i);
    const auto [xj, yj] = maxManhattanDistance(points, j);
    return min(manhattan(points, xi, yi), manhattan(points, xj, yj));
  }

 private:
  // Returns the pair of indices a and b where points[a] and points[b] have the
  // maximum Manhattan distance and a != excludedIndex and b != excludedIndex.
  pair<int, int> maxManhattanDistance(const vector<vector<int>>& points,
                                      int excludedIndex) {
    int minSum = INT_MAX;
    int maxSum = INT_MIN;
    int minDiff = INT_MAX;
    int maxDiff = INT_MIN;
    int minSumIndex = -1;
    int maxSumIndex = -1;
    int minDiffIndex = -1;
    int maxDiffIndex = -1;

    for (int i = 0; i < points.size(); ++i) {
      if (i == excludedIndex)
        continue;
      const int x = points[i][0];
      const int y = points[i][1];
      const int sum = x + y;
      const int diff = x - y;
      if (sum < minSum)
        minSum = sum, minSumIndex = i;
      if (sum > maxSum)
        maxSum = sum, maxSumIndex = i;
      if (diff < minDiff)
        minDiff = diff, minDiffIndex = i;
      if (diff > maxDiff)
        maxDiff = diff, maxDiffIndex = i;
    }

    return maxSum - minSum >= maxDiff - minDiff
               ? pair<int, int>(minSumIndex, maxSumIndex)
               : pair<int, int>(minDiffIndex, maxDiffIndex);
  }

  int manhattan(const vector<vector<int>>& points, int i, int j) {
    return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]);
  }
};


There is an undirected weighted graph with `n` vertices labeled from `0` to `n
- 1`.

You are given the integer `n` and an array `edges`, where `edges[i] = [ui, vi,
wi]` indicates that there is an edge between vertices `ui` and `vi` with a
weight of `wi`.

A walk on a graph is a sequence of vertices and edges. The walk starts and
ends with a vertex, and each edge connects the vertex that comes before it and
the vertex that comes after it. It's important to note that a walk may visit
the same edge or vertex more than once.

The cost of a walk starting at node `u` and ending at node `v` is defined as
the bitwise `AND` of the weights of the edges traversed during the walk. In
other words, if the sequence of edge weights encountered during the walk is
`w0, w1, w2, ..., wk`, then the cost is calculated as `w0 & w1 & w2 & ... &
wk`, where `&` denotes the bitwise `AND` operator.

You are also given a 2D array `query`, where `query[i] = [si, ti]`. For each
query, you need to find the minimum cost of the walk starting at vertex `si`
and ending at vertex `ti`. If there exists no such walk, the answer is `-1`.

Return the array `answer`, where `answer[i]` denotes the minimum cost of a
walk for query `i`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class UnionFind:
  def __init__(self, n: int):
    self.id = list(range(n))
    self.rank = [0] * n
    self.weight = [(1 << 17) - 1] * n

  def unionByRank(self, u: int, v: int, w: int) -> None:
    i = self._find(u)
    j = self._find(v)
    newWeight = self.weight[i] & self.weight[j] & w
    self.weight[i] = newWeight
    self.weight[j] = newWeight
    if i == j:
      return
    if self.rank[i] < self.rank[j]:
      self.id[i] = j
    elif self.rank[i] > self.rank[j]:
      self.id[j] = i
    else:
      self.id[i] = j
      self.rank[j] += 1

  def getMinCost(self, u: int, v: int) -> int:
    if u == v:
      return 0
    i = self._find(u)
    j = self._find(v)
    if i == j:
      return self.weight[i]
    else:
      return -1

  def _find(self, u: int) -> int:
    if self.id[u] != u:
      self.id[u] = self._find(self.id[u])
    return self.id[u]

class Solution:
  def minimumCost(self, n: int, edges: List[List[int]], query: List[List[int]]) -> List[int]:
    uf = UnionFind(n)

    for u, v, w in edges:
      uf.unionByRank(u, v, w)

    return [uf.getMinCost(u, v) for u, v in query]

class UnionFind {
  public UnionFind(int n) {
    id = new int[n];
    rank = new int[n];
    weight = new int[n];
    for (int i = 0; i < n; ++i)
      id[i] = i;
    // 2^17 - 1 is the minimum number in the form 2^x - 1 > 10^5.
    Arrays.fill(weight, (1 << 17) - 1);
  }

  public void unionByRank(int u, int v, int w) {
    final int i = find(u);
    final int j = find(v);
    final int newWeight = weight[i] & weight[j] & w;
    weight[i] = newWeight;
    weight[j] = newWeight;
    if (i == j)
      return;
    if (rank[i] < rank[j]) {
      id[i] = j;
    } else if (rank[i] > rank[j]) {
      id[j] = i;
    } else {
      id[i] = j;
      ++rank[j];
    }
  }

  public int getMinCost(int u, int v) {
    if (u == v)
      return 0;
    final int i = find(u);
    final int j = find(v);
    return i == j ? weight[i] : -1;
  }

  private int[] id;
  private int[] rank;
  private int[] weight;

  private int find(int u) {
    return id[u] == u ? u : (id[u] = find(id[u]));
  }
}

class Solution {
  public int[] minimumCost(int n, int[][] edges, int[][] query) {
    int[] ans = new int[query.length];
    UnionFind uf = new UnionFind(n);

    for (int[] edge : edges) {
      final int u = edge[0];
      final int v = edge[1];
      final int w = edge[2];
      uf.unionByRank(u, v, w);
    }

    for (int i = 0; i < query.length; ++i) {
      final int u = query[i][0];
      final int v = query[i][1];
      ans[i] = uf.getMinCost(u, v);
    }

    return ans;
  }
}

class UnionFind {
 public:
  // 2^17 - 1 is the minimum number in the form 2^x - 1 > 10^5.
  UnionFind(int n) : id(n), rank(n), weight(n, (1 << 17) - 1) {
    iota(id.begin(), id.end(), 0);
  }

  void unionByRank(int u, int v, int w) {
    const int i = find(u);
    const int j = find(v);
    const int newWeight = weight[i] & weight[j] & w;
    weight[i] = newWeight;
    weight[j] = newWeight;
    if (i == j)
      return;
    if (rank[i] < rank[j]) {
      id[i] = j;
    } else if (rank[i] > rank[j]) {
      id[j] = i;
    } else {
      id[i] = j;
      ++rank[j];
    }
  }

  int getMinCost(int u, int v) {
    if (u == v)
      return 0;
    const int i = find(u);
    const int j = find(v);
    return i == j ? weight[i] : -1;
  }

 private:
  vector<int> id;
  vector<int> rank;
  vector<int> weight;

  int find(int u) {
    return id[u] == u ? u : id[u] = find(id[u]);
  }
};

class Solution {
 public:
  vector<int> minimumCost(int n, vector<vector<int>>& edges,
                          vector<vector<int>>& query) {
    vector<int> ans;
    UnionFind uf(n);

    for (const vector<int>& edge : edges) {
      const int u = edge[0];
      const int v = edge[1];
      const int w = edge[2];
      uf.unionByRank(u, v, w);
    }

    for (const vector<int>& query : queries) {
      const int u = query[0];
      const int v = query[1];
      ans.push_back(uf.getMinCost(u, v));
    }

    return ans;
  }
};


Minimum Time to Visit Disappearing Nodes

There is an undirected graph of `n` nodes. You are given a 2D array `edges`,
where `edges[i] = [ui, vi, lengthi]` describes an edge between node `ui` and
node `vi` with a traversal time of `lengthi` units.

Additionally, you are given an array `disappear`, where `disappear[i]` denotes
the time when the node `i` disappears from the graph and you won't be able to
visit it.

Notice that the graph might be disconnected and might contain multiple edges.

Return the array `answer`, with `answer[i]` denoting the minimum units of time
required to reach node `i` from node 0. If node `i` is unreachable from node 0
then `answer[i]` is `-1`.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def minimumTime(self, n: int, edges: List[List[int]], disappear: List[int]) -> List[int]:
    graph = [[] for _ in range(n)]

    for u, v, w in edges:
      graph[u].append((v, w))
      graph[v].append((u, w))

    return self._dijkstra(graph, 0, disappear)

  def _dijkstra(self, graph: List[List[Tuple[int, int]]], src: int, disappear: List[int]) -> List[int]:
    dist = [math.inf] * len(graph)

    dist[src] = 0
    minHeap = [(dist[src], src)]

    while minHeap:
      d, u = heapq.heappop(minHeap)
      if d > dist[u]:
        continue
      for v, w in graph[u]:
        if d + w < disappear[v] and d + w < dist[v]:
          dist[v] = d + w
          heapq.heappush(minHeap, (dist[v], v))

    res=[]
    for d in dist:
      if d != math.inf:
        res.append(d)
      else:
        res.append(-1)
    return res

class Solution {
  public int[] minimumTime(int n, int[][] edges, int[] disappear) {
    List<Pair<Integer, Integer>>[] graph = new List[n];

    for (int i = 0; i < n; i++)
      graph[i] = new ArrayList<>();

    for (int[] edge : edges) {
      final int u = edge[0];
      final int v = edge[1];
      final int w = edge[2];
      graph[u].add(new Pair<>(v, w));
      graph[v].add(new Pair<>(u, w));
    }

    return dijkstra(graph, 0, disappear);
  }

  private int[] dijkstra(List<Pair<Integer, Integer>>[] graph, int src, int[] disappear) {
    int[] dist = new int[graph.length];
    Arrays.fill(dist, Integer.MAX_VALUE);

    dist[src] = 0;
    Queue<Pair<Integer, Integer>> minHeap =
        new PriorityQueue<>(Comparator.comparingInt(Pair::getKey)) {
          { offer(new Pair<>(dist[src], src)); } // (d, u)
        };

    while (!minHeap.isEmpty()) {
      final int d = minHeap.peek().getKey();
      final int u = minHeap.poll().getValue();
      if (d > dist[u])
        continue;
      for (Pair<Integer, Integer> pair : graph[u]) {
        final int v = pair.getKey();
        final int w = pair.getValue();
        if (d + w < disappear[v] && d + w < dist[v]) {
          dist[v] = d + w;
          minHeap.offer(new Pair<>(dist[v], v));
        }
      }
    }

    for (int i = 0; i < dist.length; ++i)
      if (dist[i] == Integer.MAX_VALUE)
        dist[i] = -1;

    return dist;
  }
}

class Solution {
 public:
  vector<int> minimumTime(int n, vector<vector<int>>& edges,
                          vector<int>& disappear) {
    vector<vector<pair<int, int>>> graph(n);

    for (const vector<int>& edge : edges) {
      const int u = edge[0];
      const int v = edge[1];
      const int w = edge[2];
      graph[u].emplace_back(v, w);
      graph[v].emplace_back(u, w);
    }

    return dijkstra(graph, 0, disappear);
  }

 private:
  vector<int> dijkstra(const vector<vector<pair<int, int>>>& graph, int src,
                       const vector<int>& disappear) {
    vector<int> dist(graph.size(), INT_MAX);

    dist[src] = 0;
    using P = pair<int, int>;  // (d, u)
    priority_queue<P, vector<P>, greater<>> minHeap;
    minHeap.emplace(dist[src], src);

    while (!minHeap.empty()) {
      const auto [d, u] = minHeap.top();
      minHeap.pop();
      if (d > dist[u])
        continue;
      for (const auto& [v, w] : graph[u])
        if (d + w < disappear[v] && d + w < dist[v]) {
          dist[v] = d + w;
          minHeap.push({dist[v], v});
        }
    }

    for (int& d : dist)
      if (d == INT_MAX)
        d = -1;

    return dist;
  }
};


You are given an undirected weighted graph of `n` nodes numbered from 0 to `n
- 1`. The graph consists of `m` edges represented by a 2D array `edges`, where
`edges[i] = [ai, bi, wi]` indicates that there is an edge between nodes `ai`
and `bi` with weight `wi`.

Consider all the shortest paths from node 0 to node `n - 1` in the graph. You
need to find a boolean array `answer` where `answer[i]` is `true` if the edge
`edges[i]` is part of at least one shortest path. Otherwise, `answer[i]` is
`false`.

Return the array `answer`.

Note that the graph may not be connected.

import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def findAnswer(self, n: int, edges: List[List[int]]) -> List[bool]:
    graph = [[] for _ in range(n)]

    for u, v, w in edges:
      graph[u].append((v, w))
      graph[v].append((u, w))

    from0 = self._dijkstra(graph, 0)
    from1 = self._dijkstra(graph, n - 1)
    return [from0[u] + w + from1[v] == from0[-1] or from0[v] + w + from1[u] == from0[-1] for u, v, w in edges]

  def _dijkstra(self, graph: List[List[Tuple[int, int]]], src: int) -> List[int]:
    dist = [10**9] * len(graph)

    dist[src] = 0
    minHeap = [(dist[src], src)]

    while minHeap:
      d, u = heapq.heappop(minHeap)
      if d > dist[u]:
        continue
      for v, w in graph[u]:
        if d + w < dist[v]:
          dist[v] = d + w
          heapq.heappush(minHeap, (dist[v], v))

    return dist

class Solution {
  // Similar to 2203. Minimum Weighted Subgraph With the Required Paths
  public boolean[] findAnswer(int n, int[][] edges) {
    boolean[] ans = new boolean[edges.length];
    List<Pair<Integer, Integer>>[] graph = new List[n];
    Arrays.setAll(graph, i -> new ArrayList<>());

    for (int[] edge : edges) {
      final int u = edge[0];
      final int v = edge[1];
      final int w = edge[2];
      graph[u].add(new Pair<>(v, w));
      graph[v].add(new Pair<>(u, w));
    }

    int[] from0 = dijkstra(graph, 0);
    int[] from1 = dijkstra(graph, n - 1);

    for (int i = 0; i < edges.length; ++i) {
      final int u = edges[i][0];
      final int v = edges[i][1];
      final int w = edges[i][2];
      ans[i] = from0[u] + w + from1[v] == from0[n - 1] || //
               from0[v] + w + from1[u] == from0[n - 1];
    }

    return ans;
  }

  private static int MAX = 1_000_000_000;

  private int[] dijkstra(List<Pair<Integer, Integer>>[] graph, int src) {
    int[] dist = new int[graph.length];
    Arrays.fill(dist, MAX);

    dist[src] = 0;
    Queue<Pair<Integer, Integer>> minHeap =
        new PriorityQueue<>(Comparator.comparingInt(Pair::getKey)) {
          { offer(new Pair<>(dist[src], src)); } // (d, u)
        };

    while (!minHeap.isEmpty()) {
      final int d = minHeap.peek().getKey();
      final int u = minHeap.poll().getValue();
      if (d > dist[u])
        continue;
      for (Pair<Integer, Integer> pair : graph[u]) {
        final int v = pair.getKey();
        final int w = pair.getValue();
        if (d + w < dist[v]) {
          dist[v] = d + w;
          minHeap.offer(new Pair<>(dist[v], v));
        }
      }
    }

    return dist;
  }
};

class Solution {
 public:
  // Similar to 2203. Minimum Weighted Subgraph With the Required Paths
  vector<bool> findAnswer(int n, vector<vector<int>>& edges) {
    vector<bool> ans;
    vector<vector<pair<int, int>>> graph(n);

    for (const vector<int>& edge : edges) {
      const int u = edge[0];
      const int v = edge[1];
      const int w = edge[2];
      graph[u].emplace_back(v, w);
      graph[v].emplace_back(u, w);
    }

    const vector<int> from0 = dijkstra(graph, 0);
    const vector<int> from1 = dijkstra(graph, n - 1);

    for (const vector<int>& edge : edges) {
      const int u = edge[0];
      const int v = edge[1];
      const int w = edge[2];
      ans.push_back(from0[u] + w + from1[v] == from0[n - 1] ||
                    from0[v] + w + from1[u] == from0[n - 1]);
    }

    return ans;
  }

 private:
  static constexpr int kMax = 1'000'000'000;

  vector<int> dijkstra(const vector<vector<pair<int, int>>>& graph, int src) {
    vector<int> dist(graph.size(), kMax);

    dist[src] = 0;
    using P = pair<int, int>;  // (d, u)
    priority_queue<P, vector<P>, greater<>> minHeap;
    minHeap.emplace(dist[src], src);

    while (!minHeap.empty()) {
      const auto [d, u] = minHeap.top();
      minHeap.pop();
      if (d > dist[u])
        continue;
      for (const auto& [v, w] : graph[u])
        if (d + w < dist[v]) {
          dist[v] = d + w;
          minHeap.emplace(dist[v], v);
        }
    }

    return dist;
  }
};