是树上 k 级祖先的板子,以下代码在 VS2022 c++14 时测样例爆读取访问权限冲突。
#pragma warning(disable:4996)
#include <iostream>
#include <vector>
using namespace std;
#define re register
typedef long long int ll;
const int maxn = 5e5 + 10;
const ll inf = 2147483647LL;
struct edge {
int to, nxt;
}node[maxn]; int head[maxn], cnt = 0;
inline void add(int u, int v) {
node[cnt].nxt = head[u];
node[cnt].to = v;
head[u] = cnt++;
}
int fa[maxn][22], top[maxn], dep[maxn], son[maxn], len[maxn];
void dfs1(int u, int f) {
fa[u][0] = f; dep[u] = dep[f] + 1;
for (int i = 1; i <= 20; i++) {
if (fa[u][i - 1])fa[u][i] = fa[fa[u][i - 1]][i - 1];
else break;
}
int md = 0;
for (int i = head[u]; ~i; i = node[i].nxt) {
int v = node[i].to;
if (v != f) {
dfs1(v, u);
if (dep[v] > md)md = dep[v], son[u] = v;
}
}
}
vector<int>ld[maxn], lu[maxn];
void dfs2(int u, int t) {
ld[t].push_back(u); ++len[t]; top[u] = t;
if (son[u])dfs2(son[u], t);
for (int i = head[u]; ~i; i = node[i].nxt) {
int v = node[i].to;
if (v != fa[u][0] && v != son[u]) {
dfs2(v, v);
}
}
int p = t, ct = 1;
while (ct <= len[t] && p) {
lu[t].push_back(p);//在这处爆RE,但 t=5, p=5,似乎一切正常
p = fa[p][0], ++ct;
}
}
int Log[maxn];
inline int query(int u, int k) {
int l = Log[k];
u = fa[u][l]; k -= 1 << l;
if (dep[top[u]] <= dep[u] - k)return ld[top[u]][dep[u] - k - dep[top[u]]];
else return lu[top[u]][dep[top[u]] + k - dep[u]];
}
#define ui unsigned int
ui s;
inline ui get(ui x) {
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return s = x;
}
int main() {
memset(head, -1, sizeof(head));
int n, q, rt = 0; scanf("%d%d%u", &n, &q, &s);
for (int i = 2; i <= (1 << 20); i++)Log[i] = Log[i >> 1] + 1;
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
if (x)add(i, x), add(x, i);
else rt = i;
}
dfs1(rt, 0); dfs2(rt, rt); ll ans = 0, sum = 0;
for (int i = 1; i <= q; i++) {
int x = (get(s) ^ ans) % n + 1;
int k = (get(s) ^ ans) % dep[x];
if (k == 0)ans = x;
else ans = query(x, k);
sum ^= i * ans;
}
printf("%lld\n", sum);
return 0;
}
附样例
6 3 7
5 5 2 2 0 3