题目大意
给出一个有根树,每一个结点有一个值 ki ,表示到达这个点的的石子可以向根跳 ki 步,现在有两种操作:1)改变一个点的 ki 值,2)查询向一个点丢石子时,石子弹几次才会走出树。
解题思路
这道题其实就是弹飞绵羊那道题的升级版,两种操作可以分别被理解为:改变某个节点的父节点,查询某个结点到根节点的距离。感觉当场只有100人过掉有点少了吧。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=int(1e5)+11, OUT=int(1e5)+3;
struct Node {
int key,siz;
Node *ch[2],*fa;
Node();
Node(int);
int son() {
if(this==fa->ch[0]) return 0;
if(this==fa->ch[1]) return 1;
return -1;
}
void maintain();
}*null, node[maxn];
Node:: Node():key(-1) {
siz=null?1:0;
ch[0]=ch[1]=fa=null;
}
Node:: Node(int _):key(_) {
siz=null?1:0;
ch[0]=ch[1]=fa=null;
}
void Node:: maintain() {
siz=ch[0]->siz+1+ch[1]->siz;
return;
}
void Rotate(Node* cur,int dir) {
Node* tmp=cur->ch[dir^1];
cur->ch[dir^1]=tmp->ch[dir], tmp->ch[dir]->fa=cur;
tmp->ch[dir]=cur;
cur->maintain(), tmp->maintain();
if(~cur->son()) cur->fa->ch[cur->son()]=tmp;
tmp->fa=cur->fa, cur->fa=tmp;
return;
}
void Splay(Node* cur) {
while(~cur->son()) {
int dir=cur->son();
if(dir==cur->fa->son()) Rotate(cur->fa->fa,dir^1);
Rotate(cur->fa,dir^1);
}
return;
}
void Access(Node* cur) {
Node* tmp=null;
while(cur!=null) {
Splay(cur);
cur->ch[1]=tmp, cur->maintain();
tmp=cur, cur=cur->fa;
}
return;
}
void Modify(Node* x,Node* y) {
Access(x), Splay(x);
x->ch[0]->fa=null;
x->ch[0]=null, x->maintain();
x->fa=y;
return;
}
void init_null() {
null=new Node(-1);
null->ch[0]=null->ch[1]=null->fa=null;
return;
}
struct Edge {
int to,next;
Edge() {}
Edge(int a,int b):to(a),next(b) {}
}eage[maxn*2];
int n;
int head[maxn], tot=0;
int dep[maxn];
int fa[maxn][30];
int a[maxn];
void add_eage(int u,int v) {
eage[tot]=Edge(v,head[u]), head[u]=tot++;
return;
}
void init() {
register int i;
tot=0;
for(i=1;i<=n;++i) {
head[i]=-1;
}
return;
}
void dfs(int u,int d) {
register int i;
dep[u]=d;
for(i=1;(1<<i)<=d;++i)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(i=head[u];~i;i=eage[i].next) {
fa[eage[i].to][0]=u;
dfs(eage[i].to,d+1);
}
return;
}
int get_fa(int u,int k) {
if(k>dep[u]) return OUT;
int i=0;
for(;k;k>>=1,i++) if(k&1) u=fa[u][i];
return u;
}
void work() {
scanf("%d",&n);
init();
register int i,v;
for(i=0;i<30;++i)
fa[1][i]=OUT;
for(i=2;i<=n;++i) {
scanf("%d",&v);
add_eage(v,i);
}
dfs(1,0);
for(i=1;i<=n;++i) {
scanf("%d",&a[i]);
node[i]=Node(i);
int g=get_fa(i,a[i]);
if(g<=n) node[i].fa=&node[g];
}
int m,op,x,y;
scanf("%d",&m);
for(i=1;i<=m;++i) {
scanf("%d%d",&op,&x);
if(op==1) {
Access(&node[x]); Splay(&node[x]);
printf("%d\n",node[x].siz);
} else {
scanf("%d",&y);
int g=get_fa(x,y);
if(g<=n) Modify(&node[x],&node[g]);
else Modify(&node[x],null);
}
}
return;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
#endif
init_null();
int T;
for(scanf("%d",&T);T;T--)
work();
return 0;
}