题解 P5305 【[GXOI/GZOI2019]旧词】

GKxx

2019-04-22 17:46:45

Solution

来个稍微有点不一样的 其实大体思路大家都已经讲得比较到位了 就是把[LNOI2014]LCA那题改一改,把加$1$改成加$k$次差分 可是询问离线什么的最讨厌了 我这种懒人当然是写可持久化线段树了 空间要开大一点,注意标记下传的时候也要复制节点 按可持久化的方法写就行了 所以其实这题完全可以强制在线嘛! ```cpp #include <cctype> #include <cstdio> #include <climits> #include <algorithm> template <typename T> inline void read(T& x) { int f = 0, c = getchar(); x = 0; while (!isdigit(c)) f |= c == '-', c = getchar(); while (isdigit(c)) x = x * 10 + c - 48, c = getchar(); if (f) x = -x; } template <typename T, typename... Args> inline void read(T& x, Args&... args) { read(x); read(args...); } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + 48); } template <typename T> inline void writeln(T x) { write(x); puts(""); } template <typename T> inline bool chkmin(T& x, const T& y) { return y < x ? (x = y, true) : false; } template <typename T> inline bool chkmax(T& x, const T& y) { return x < y ? (x = y, true) : false; } typedef long long LL; const LL mod = 998244353; const int maxn = 5e4 + 207; inline LL qpow(LL x, LL k) { LL s = 1; for (; k; x = x * x % mod, k >>= 1) if (k & 1) s = s * x % mod; return s; } int v[maxn], head[maxn], next[maxn], etot; int dep[maxn], top[maxn], fa[maxn], size[maxn], son[maxn], dfn[maxn], arcdfn[maxn], xys; LL s[maxn], a[maxn]; int n, q, K; inline void ae(int x, int y) { v[++etot] = y; next[etot] = head[x]; head[x] = etot; } void dfs(int x) { dep[x] = dep[fa[x]] + 1; size[x] = 1; for (int i = head[x]; i; i = next[i]) { fa[v[i]] = x; dfs(v[i]); size[x] += size[v[i]]; if (size[v[i]] >= size[son[x]]) son[x] = v[i]; } } void dfs(int x, int t) { top[x] = t; dfn[x] = ++xys; arcdfn[xys] = x; if (son[x]) dfs(son[x], t); for (int i = head[x]; i; i = next[i]) if (v[i] != son[x]) dfs(v[i], v[i]); } struct Node { int lc, rc; LL sum, add; Node() : lc(0), rc(0), sum(0), add(0) {} }; Node T[maxn << 7]; int root[maxn], tot; inline void update(int o) { T[o].sum = (T[T[o].lc].sum + T[T[o].rc].sum) % mod; } inline void pushdown(int o, int l, int mid, int r) { if (T[o].add) { LL &d = T[o].add; T[++tot] = T[T[o].lc]; T[o].lc = tot; T[++tot] = T[T[o].rc]; T[o].rc = tot; T[T[o].lc].sum = (T[T[o].lc].sum + d * (s[mid] - s[l - 1] + mod) % mod) % mod; T[T[o].rc].sum = (T[T[o].rc].sum + d * (s[r] - s[mid] + mod) % mod) % mod; T[T[o].lc].add += d; T[T[o].rc].add += d; d = 0; } } void modify(int &o, int lb, int rb, int l, int r) { if (l > rb || r < lb) return; T[++tot] = T[o]; o = tot; if (l <= lb && r >= rb) { T[o].sum = (T[o].sum + s[rb] - s[lb - 1] + mod) % mod; ++T[o].add; return; } int mid = (lb + rb) >> 1; pushdown(o, lb, mid, rb); modify(T[o].lc, lb, mid, l, r); modify(T[o].rc, mid + 1, rb, l, r); update(o); } LL query(int o, int lb, int rb, int l, int r) { if (!o || l > rb || r < lb) return 0; if (l <= lb && r >= rb) return T[o].sum; int mid = (lb + rb) >> 1; pushdown(o, lb, mid, rb); return (query(T[o].lc, lb, mid, l, r) + query(T[o].rc, mid + 1, rb, l, r)) % mod; } inline void add(int x, int i) { for (; x; x = fa[top[x]]) modify(root[i], 1, n, dfn[top[x]], dfn[x]); } inline LL query(int x, int i) { LL ans = 0; for (; x; x = fa[top[x]]) ans = (ans + query(root[i], 1, n, dfn[top[x]], dfn[x])) % mod; return ans; } int main() { read(n, q, K); for (int i = 2, f; i <= n; ++i) read(f), ae(f, i); dfs(1); dfs(1, 1); for (int i = 1; i <= n; ++i) a[i] = (qpow(dep[i], K) - qpow(dep[i] - 1, K) + mod) % mod; for (int i = 1; i <= n; ++i) s[i] = (s[i - 1] + a[arcdfn[i]]) % mod; for (int i = 1; i <= n; ++i) { root[i] = root[i - 1]; add(i, i); } while (q--) { int x, y; read(x, y); writeln(query(y, x)); } return 0; } ```