boolf0(vector<int> &a, int m, int k){ int s = 0; for (int i = 0, j = 0; i < a.size(); i++) { while (a[i] - a[j] > m) j++; s += i - j; } return s >= k; }
intf(vector<int> &a, int k){ sort(a.begin(), a.end());
int g = 0; int h = a.back() - a[0]; while (g < h) { int m = g + (h - g) / 2; if (f0(a, m, k)) { h = m; } else { g = m + 1; } }
return g; }
intmain(){ int n, k; cin >> n >> k; vector<int> a(n, 0); for (int i = 0; i < n; i++) { cin >> a[i]; } cout << f(a, k) << endl; return0; }
int n, m, deg[MAXN]; std::vector<int> E[MAXN]; longlong k, f[MAXN];
intnext(std::vector<int> cand, longlong &k){ std::sort(cand.begin(), cand.end()); for (int u : cand) { if (①) return u; k -= f[u]; } return-1; }
intmain(){ std::cin >> n >> m >> k; for (int i = 0; i < m; ++i) { int u, v; std::cin >> u >> v; // 一条从u到v的边 E[u].push_back(v); ++deg[v]; } std::vector<int> Q; for (int i = 0; i < n; ++i) if (!deg[i]) Q.push_back(i); for (int i = 0; i < n; ++i) { int u = Q[i]; for (int v : E[u]) { if (②) Q.push_back(v); --deg[v]; } } std::reverse(Q.begin(), Q.end()); for (int u : Q) { f[u] = 1; for (int v : E[u]) f[u] = ③; } int u = next(Q, k); std::cout << u << std::endl; while (④) { ⑤; u = next(E[u], k); std::cout << u << std::endl; } return0; }
解析:
f[u] 表示以 u 为起点的路径数,k 表示要求的路径第 k 小,此处若 k<=f[u] 则说明要求的路径经过顶点 u。
voidsolve(int l, int r){ if (l + 1 == r) { ans += a[l]; return; } int mid = (l + r) >> 1; std::vector<int> pre(a + mid, a + r); for (int i = 1; i < r - mid; ++i) ①; std::vector<longlong> sum(r - mid + 1); for (int i = 0; i < r - mid; ++i) sum[i + 1] = sum[i] + pre[i]; for (int i = mid - 1, j = mid, max = 0; i >= l; --i) { while (j < r && ②) ++j; max = std::max(max, a[i]); ans += ③; ans += ④; } solve(l, mid); solve(mid, r); }
intmain(){ std::cin >> n; for (int i = 0; i < n; ++i) std::cin >> a[i]; ⑤; std::cout << ans << std::endl; return0; }
这一道完善程序题最大的难点在于要看懂上述代码究竟怎样分治。 上述代码的分治部分对于区间 $[ l , r )$ 主要做了以下几件事: