洛谷P16762 [GKS 2020 #D] Locked Doors 题解 笛卡尔树+LCA
题目链接:https://www.luogu.com.cn/problem/P16762
解题思路完全来自 GX6zm大佬的博客。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int T, n, Q, idx, D[maxn], ls[maxn], rs[maxn], rt, lb[maxn], rb[maxn], fa[maxn][18];
void init() {
fill(ls+1, ls+n, 0);
fill(rs+1, rs+n, 0);
idx = n;
}
void dfs(int &u, int p, int l, int r) {
if (!u) {
u = idx++;
}
fa[u][0] = p;
lb[u] = l;
rb[u] = r;
if (u < n) {
dfs(ls[u], u, l, u);
dfs(rs[u], u, u+1, r);
}
}
int cal(int s, int k) {
if (k == 1) return s;
int u = n - 1 + s;
for (int i = 17; i >= 0; i--) {
int p = fa[u][i];
if (rb[p] - lb[p] + 1 < k)
u = p;
}
int p = fa[u][0];
int cnt = k - (rb[u] - lb[u] + 1);
if (lb[u] == lb[p]) return p + cnt;
return p + 1 - cnt;
}
void solve() {
stack<int> stk;
for (int i = 1; i < n; i++) {
int last = 0;
while (!stk.empty() && D[stk.top()] < D[i]) {
last = stk.top();
stk.pop();
}
if (!stk.empty()) rs[stk.top()] = i;
else rt = i;
ls[i] = last;
stk.push(i);
}
dfs(rt, rt, 1, n);
assert(idx == 2 * n);
for (int i = 1; i <= 17; i++)
for (int u = 1; u < 2*n; u++)
fa[u][i] = fa[ fa[u][i-1] ][i-1];
while (Q--) {
int s, k;
scanf("%d%d", &s, &k);
int ans = cal(s, k);
printf(" %d", ans);
}
putchar('\n');
}
int main() {
scanf("%d", &T);
for (int cas = 1; cas <= T; cas++) {
printf("Case #%d:", cas);
scanf("%d%d", &n, &Q);
init();
for (int i = 1; i < n; i++)
scanf("%d", D+i);
solve();
}
return 0;
}
浙公网安备 33010602011771号