树上 k 级祖先非长剖做法

预处理倍增链顶复杂度 \(O(n\log\log n-q\log\log n)\)
类似 LCA 跳就好了。

参考 @YLWang

#include <bits/stdc++.h>
#define int long long
using namespace std;

template <typename T> inline void read(T &x) {
  x = 0; char ch = getchar();
  while (!isdigit(ch)) ch = getchar();
  while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
}

const int N = 5e5 + 10;
int n, q, s, idx, fa[N], dep[N], siz[N];
int rt, dfn[N], id[N], tp[N][6];
vector <int> G[N];

inline void dfs1(int cur, int f) {
  fa[cur] = f, dep[cur] = dep[f] + 1, siz[cur] = 1;
  for (auto to: G[cur])
    dfs1(to, cur), siz[cur] += siz[to];
  return ;
}

inline void dfs2(int cur, int Tp) {
  int heavyson = 0; dfn[cur] = ++idx;
  id[idx] = cur, tp[cur][0] = Tp;
  for (int i = 1; i < 5; ++i)
    tp[cur][i] = tp[fa[tp[cur][i - 1]]][i - 1];
  for (auto to: G[cur])
    if (siz[to] > siz[heavyson]) heavyson = to;
  if (!heavyson) return ; dfs2(heavyson, Tp);
  for (auto to: G[cur])
    if (to != fa[cur] && to != heavyson) dfs2(to, to);
  return ;
}

inline int kth(int cur, int k) {
  for (int i = 4; ~i; --i)
    if (tp[cur][i] && k > dep[cur] - dep[tp[cur][i]])
      k -= dep[cur] - dep[tp[cur][i]] + 1, cur = fa[tp[cur][i]];
  if (!cur) return 0;
//  cout << "ID:" << id[dfn[cur] - k] << endl;
  return id[dfn[cur] - k];
}

inline int get(unsigned x) {
	x ^= x << 13, x ^= x >> 17;
	x ^= x << 5; return s = (int)x;
}

signed main() {
  read(n), read(q), read(s);
  for (int i = 1; i <= n; ++i) {
    int f; read(f); if (!f) { rt = i; continue; }
    G[f].emplace_back(i);
  }
  dfs1(rt, 0), dfs2(rt, rt);
  int ans = 0, res = 0;
  for (int i = 1; i <= q; ++i) {
    int cur = (get(s) ^ ans) % n + 1;
    int k = (get(s) ^ ans) % dep[cur];
    ans = kth(cur, k); res ^= (i * ans);
  }
  cout << res << endl;
  return 0;
}
posted @ 2022-09-05 14:42  MistZero  阅读(22)  评论(0编辑  收藏  举报