Tree
官方题解:
ps:长见识了,把DFS序先映射到1~n,然后再分块。维护块内合适的信息,就能使修改的复杂度降到 n1/2。当然询问的代价也是 n1/2. 太优秀啦,羞耻的坦白:看了大佬的代码,默写了一遍。解释一下重要的变量,cnt[ ]:跳出当前块的步数,net[ ]:跳出当前块后所在的节点(下一块的第一个节点),pre[ ]:当前节点 i 跳 a[ i ] 步后所在的节点。剩下的是分块和映射需要的变量。
inline void upd(int &x, int y) { x < y && (x = y); } const int N = 100005; int n, m, tot, DFS_Time; int head[N], cnt[N], net[N], pre[N], pa[N][20], a[N], belong[N], l[N], r[N], id[N]; struct node { int to, next; } G[N]; void Inite() { mem(head, -1); tot = DFS_Time = 0; } void addedge(int u, int v) { G[tot].to = v, G[tot].next = head[u], head[u] = tot++; } void DFS(int u, int p) { pa[u][0] = p; id[u] = ++DFS_Time; for (int i = head[u]; ~i; i = G[i].next) DFS(G[i].to, u); } void Build() { int block = (int)sqrt(n); // 块的大小 int mNum = n / block + (n % block != 0); // 块的个数 for (int i = 1; i <= n; ++i) belong[i] = (i - 1) / block + 1; for (int i = 1; i <= mNum; ++i) { l[i] = (i - 1) * block + 1; r[i] = i * block; } r[mNum] = n; DFS(1, 0); for (int i = 1; i < 20; ++i) for (int j = 1; j <= n; ++j) pa[j][i] = pa[pa[j][i - 1]][i - 1]; } int Find(int u, int t) { for (int i = 19; ~i; --i) if ((t >> i) & 1) u = pa[u][i]; return u; } void DFS2(int u) { int p = Find(u, a[u]); pre[id[u]] = id[p]; if (id[p] < l[belong[id[u]]]) cnt[id[u]] = 1, net[id[u]] = id[p]; else cnt[id[u]] = cnt[id[p]] + 1, net[id[u]] = net[id[p]]; for (int i = head[u]; ~i; i = G[i].next) DFS2(G[i].to); } int Query(int x) { int ans = 0; while(x) { ans += cnt[x]; x = net[x]; } return ans; } void Update(int u, int x) { a[u] = x; int p = Find(u, x); pre[id[u]] = id[p]; int L = l[belong[id[u]]]; int R = r[belong[id[u]]]; if (id[p] < L) cnt[id[u]] = 1, net[id[u]] = id[p]; else cnt[id[u]] = cnt[id[p]] + 1, net[id[u]] = net[id[p]]; for (int i = id[u] + 1; i <= R; ++i) if (pre[i] >= L) { cnt[i] = cnt[pre[i]] + 1; net[i] = net[pre[i]]; } } int main() { //freopen("D:\\a.in", "r", stdin); //freopen("D:\\1.txt", "w", stdout); BEGIN() { Inite(); sc(n); for (int i = 2; i <= n; ++i) { int x; sc(x); addedge(x, i); } for (int i = 1; i <= n; ++i) sc(a[i]); Build(); DFS2(1); sc(m); for (int i = 1; i <= m; ++i) { int op, u, x; sc(op), sc(u); if (op == 1) { pr(Query(id[u])); } else { sc(x); Update(u, x); } } } return 0; }