Approach
Depth-first search
For Kth Smallest Path Xor Sum, the implementation follows one branch at a time, making it suitable for components, trees, backtracking, or dependency exploration.
- Define the state carried into one recursive or stack frame.
- Mark or choose the current state before exploring children.
- Combine child results or undo the choice when the branch finishes.
Code notes
- 117 lines of C++ from the credited upstream file kth-smallest-path-xor-sum.cpp.
- The implementation visibly relies on sequence storage.
- 12 loop blocks detected, together with recursive traversal.
Complexity
Count unique states for graph traversal; for backtracking, count the branching factor and maximum depth.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
123 4#include <ext/pb_ds/assoc_container.hpp>5#include <ext/pb_ds/tree_policy.hpp>6using namespace __gnu_pbds;7 89class Solution {10public:11 vector<int> kthSmallest(vector<int>& par, vector<int>& vals, vector<vector<int>>& queries) {12 vector<vector<int>> adj(size(par));13 for (int u = 0; u < size(par); ++u) {14 const auto& p = par[u];15 if (p != -1) {16 adj[p].emplace_back(u);17 }18 }19 vector<vector<int>> lookup(size(adj));20 for (int i = 0; i < size(queries); ++i) {21 lookup[queries[i][0]].emplace_back(i);22 }23 const auto& iter_dfs = [&]() {24 using ordered_set = tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>;25 vector<ordered_set> os(size(adj));26 vector<int> idxs(size(adj));27 iota(begin(idxs), end(idxs), 0);28 const auto& small_to_large_merge = [&](auto& i, auto& j) { 29 if (size(os[i]) < size(os[j])) {30 swap(i, j); 31 }32 for (const auto& x : os[j]) { 33 os[i].insert(x); 34 }35 };36 37 vector<int> result(size(queries), -1);38 vector<tuple<int, int, int>> stk = {{1, 0, 0}};39 while (!empty(stk)) {40 auto [step, u, curr] = stk.back(); stk.pop_back();41 if (step == 1) {42 curr ^= vals[u];43 os[idxs[u]].insert(curr);44 stk.emplace_back(2, u, curr);45 for (const auto& v : adj[u]) {46 stk.emplace_back(1, v, curr);47 }48 } else if (step == 2) {49 for (const auto& v : adj[u]) {50 small_to_large_merge(idxs[u], idxs[v]);51 }52 for (const auto& i : lookup[u]) { 53 if (queries[i][1] - 1 < size(os[idxs[u]])) {54 result[i] = *(os[idxs[u]].find_by_order(queries[i][1] - 1));55 }56 }57 }58 }59 return result;60 };61 62 return iter_dfs();63 }64};65 666768#include <ext/pb_ds/assoc_container.hpp>69#include <ext/pb_ds/tree_policy.hpp>70using namespace __gnu_pbds;7172class Solution2 {73public:74 vector<int> kthSmallest(vector<int>& par, vector<int>& vals, vector<vector<int>>& queries) {75 vector<vector<int>> adj(size(par));76 for (int u = 0; u < size(par); ++u) {77 const auto& p = par[u];78 if (p != -1) {79 adj[p].emplace_back(u);80 }81 }82 vector<vector<int>> lookup(size(adj));83 for (int i = 0; i < size(queries); ++i) {84 lookup[queries[i][0]].emplace_back(i);85 }86 const auto& small_to_large_merge = [&](auto& ptr1, auto& ptr2) { 87 if (size(*ptr1) < size(*ptr2)) {88 swap(ptr1, ptr2); 89 }90 for (const auto& x : *ptr2) { 91 ptr1->insert(x); 92 }93 };94 95 vector<int> result(size(queries), -1);96 using ordered_set = tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>;97 const function<unique_ptr<ordered_set> (int, int)> dfs = [&](int u, int curr) {98 curr ^= vals[u];99 auto ptr = make_unique<ordered_set>();100 ptr->insert(curr);101 for (const auto& v : adj[u]) {102 auto new_ptr = dfs(v, curr);103 small_to_large_merge(ptr, new_ptr);104 }105 for (const auto& i : lookup[u]) { 106 if (queries[i][1] - 1 < size(*ptr)) {107 result[i] = *(ptr->find_by_order(queries[i][1] - 1));108 }109 }110 return ptr;111 };112 113 dfs(0, 0);114 return result;115 }116};117