intget_lca(int x, int y){ if (dep[x] < dep[y]) { swap(x, y); } int diff = dep[x] - dep[y]; for (int bit = 0; bit <= 20; bit++) { if (diff >> bit & 1) { x = f[bit][x]; } } if (x == y) { return x; } for (int bit = 20; bit >= 0; bit--) { if (f[bit][x] != f[bit][y]) { x = f[bit][x]; y = f[bit][y]; } } return f[0][x]; }
枚举 y,找到祖先节点中最浅的满足 d(x,y)⩽Wy 的 x。那么 x 到 y 中所有的点都符合题意,答案都需要 +1,树上前缀和。
1 2 3 4 5 6 7 8 9 10 11
i64 rem = w[x]; for (int bit = 30; bit >= 0; bit--) { if (f[bit][x] != -1 && g[bit][x] <= rem) { rem -= g[bit][x]; x = f[bit][x]; } } diff[y]++; if (f[0][x] != -1) { diff[f[0][x]]--; }
for (int bit = 1; bit < 20; bit++) { if (f[bit - 1][x] != -1) { f[bit][x] = f[bit - 1][f[bit - 1][x]]; g[bit][x] = g[bit - 1][f[bit - 1][x]] + g[bit - 1][x]; if (g[bit][x] > INF) { g[bit][x] = INF; } } }
int y = x; while (y >= 2) { for (int bit = 19; bit >= 0; bit--) { if (f[bit][y] != -1) { auto fy = f[bit][y]; auto gy = g[bit][y]; if (gy < pos && pos <= gy + len[fy]) { pos -= gy; y = fy; } } } if (y < 2) { break; }
if (pos <= len[lc[y]]) { y = lc[y]; } else { pos -= len[lc[y]]; y = rc[y]; } } std::cout << y << "\n"; } return; }
Given a non-decreasing sequence A. Given Q queries. For a query [L,R], answer the length of the longest subsequence b of the subarray A[L,R] such that bi+2>Z+bi for all i.
vector<ll> a(n + 1); for (int i = 1; i <= n; i++) { cin >> a[i]; }
vector<array<int, maxB>> p(n + 2); vector<int> d(n + 2); vector<array<int, maxB>> f(n + 2), g(n + 2); p[n + 1].fill(n + 1); f[n + 1].fill(n + 1); for (int i = n; i >= 1; i--) { p[i][0] = upper_bound(a.begin(), a.end(), a[i] + z) - a.begin(); d[i] = d[p[i][0]] + 1; for (int bit = 1; bit < maxB; bit++) { p[i][bit] = p[p[i][bit - 1]][bit - 1]; } int x = i, y = i + 1; g[i][0] = d[x] + d[y]; for (int bit = maxB - 1; bit >= 0; bit--) { if (d[p[x][bit]] >= d[y]) x = p[x][bit]; } for (int bit = maxB - 1; bit >= 0; bit--) { if (d[p[y][bit]] >= d[x]) y = p[y][bit]; } if (x == y) { f[i][0] = x; } elsefor (int bit = maxB - 1; bit >= 0; bit--) { if (p[x][bit] != p[y][bit]) { x = p[x][bit]; y = p[y][bit]; } f[i][0] = p[x][0]; } g[i][0] -= d[f[i][0]] * 2; for (int bit = 1; bit < maxB; bit++) { f[i][bit] = f[f[i][bit - 1]][bit - 1]; g[i][bit] = g[i][bit - 1] + g[f[i][bit - 1]][bit - 1]; } }
int q; cin >> q;
while (q--) { int l, r; cin >> l >> r; int res = 0; for (int bit = maxB - 1; bit >= 0; bit--) { if (f[l][bit] <= r) { res += g[l][bit]; l = f[l][bit]; } } for (auto cur : {l, l + 1}) { for (int bit = maxB - 1; bit >= 0; bit--) { if (p[cur][bit] <= r) { res += (1 << bit); cur = p[cur][bit]; } } if (cur <= r) { res++; } } cout << res << "\n"; } }
constint V = 2e5 + 10; // 这里要稍微开大一点 vector<int> factor[V]; int Q, M; cin >> Q >> M; for (int p = 1; p < V; p++) { for (int i = p; i < V; i += p) { factor[i].push_back(p); } } vector<int> l(V), r(V); // A' 可以由 A in l[A']-r[A'] 得到 for (int i = 1; i < V; i++) { auto it = upper_bound(factor[i].begin(), factor[i].end(), M); it--; int p = *it;
l[i] = i - p / 2; r[i] = i + (p - 1) / 2; l[i] = max(l[i], 0); r[i] = min(r[i], V - 1); } l[0] = 0; r[0] = (M - 1) / 2; RMQ<int, less<>> L(l); RMQ<int, greater<>> R(r); while (Q--) { int A, B; cin >> A >> B; auto solve = [&](int A, int B) { int l = B, r = B; ll ans = 1; for (;;) { int nl = L(l, r + 1); // 扩张一次 int nr = R(l, r + 1); if (nl == l && nr == r) { // 扩张失败 return-1ll; } if (nl <= A && A <= nr) { return ans; } l = nl, r = nr; ans += 1; } return ans; }; cout << solve(A, B) << endl; }
( 止步于此 )
题解说要倍增,恍然大悟。连续多次操作是可以打包的。直接把复杂度降低为 log? 级别,? 是操作次数。显然操作次数不会超过 2N,现在管他有没有神秘定理都不可能 T 了。
vector<RMQ<int, less<>>> L{ l }; vector<RMQ<int, greater<>>> R{ r }; for (int _ = 1; _ < 20; _++) { auto rmq1 = L.back(); auto rmq2 = R.back(); vector<int> l(V), r(V); for (int i = 0; i < V; i++) { l[i] = rmq1(rmq1(i, i + 1), rmq2(i, i + 1) + 1); r[i] = rmq2(rmq1(i, i + 1), rmq2(i, i + 1) + 1); } L.push_back(l); R.push_back(r); } while (q--) { int A, B; cin >> A >> B; int l = B, r = B; ll ans = 1; for (int bit = 19; bit >= 0; bit--) { int nl = L[bit](l, r + 1); int nr = R[bit](l, r + 1); if (nr < A || A < nl) { l = nl, r = nr; ans += 1ll << bit; } } if (ans == (1 << 20)) { cout << -1 << endl; } else { cout << ans << endl; } }
There are Q queries. For each query, given a starting vertex Vi and a maximum of Ki allowed moves towards an ancestor node, find the maximum distance between Vi and any reachable vertex.
gk(x):从节点 x 向上跳跃 1 到 2k 步的这中间任何一个祖先节点,拐进其他分支所能获得的最大路径长度。
1 2 3 4 5 6 7 8
for (int bit = 1; bit < 20; bit++) { for (int x = 0; x < N; x++) { if (p[bit - 1][x] != -1) { p[bit][x] = p[bit - 1][p[bit - 1][x]]; g[bit][x] = std::max(g[bit - 1][x], g[bit - 1][p[bit - 1][x]] + (1 << (bit - 1))); } } }