[HEOI2016/TJOI2016]树
nearfa[i] 表示 点i 最近的一个打了标记的祖先,默认1
t[i] 表示 这个点最后一次被查询是在第几次标记之后,默认1
cnt 表示 执行了几次标记操作 ,为了方便,cnt从1开始
执行标记操作时,如果这个点已经被标记了,就不用再标记了。
否则标记,cnt++;
find(u) 函数:(递归实现)
如果点u被标记,返回u (废话);
如果t[u]==cnt (在最后一次标记后已经访问过),直接返回nearfa[u] ;
否则, 将 t[u] 设为cnt,同时将 nearfa[u] 设为 find(fa[u]) , 返回 ; (递归实现)
#include<bits/stdc++.h> using namespace std; const int N=1e5+5; int n,q,fa[N],fl[N],t[N],cl[N],cnt=1; inline int find(int u) { if (fl[u]) return u; if (t[u]==cnt) return cl[u]; t[u]=cnt; return cl[u]=find(fa[u]); } int main() { scanf("%d%d",&n,&q); for (register int i=1,u,v;i<=n;i++) { scanf("%d%d",&u,&v); fa[v]=u; } for (register int i=1;i<=n;i++) t[i]=cl[i]=1; fl[1]=1,fa[1]=1; for (register int i=1;i<=q;i++) { char op;int u; cin>>op>>u; if (op=='C') { if (!fl[u]) fl[u]=1;cnt++; } else printf("%d\n",find(u)); } return 0; }
愿你走出半生,归来仍是少年