Live2D

[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;
}
posted @ 2020-01-16 16:23  γひん0ΖΖƦ  阅读(112)  评论(0编辑  收藏  举报