洛谷4092 树
题目:https://www.luogu.org/problemnew/show/P4092
也考虑过离线。但没有想到倒序会很方便。
题解:考虑记录每个点的最近标记祖先。
对于离标记点很远的点,岂不是要慢慢找过去?
所以想到可以路径压缩的并查集。
并查集在此题中的特点是删点很容易,删x就是把fa[x]=x改成fa[x]=(x的直接父亲),所以可以倒序离线!
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=100005; int n,q,fa[N],cz[N],ans[N],ff[N],cnt[N],ct; bool b[N]; int find(int a) { if(fa[a]==a)return a; return fa[a]=find(fa[a]); } int main() { scanf("%d%d",&n,&q); int x,y;char ch; for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); ff[y]=x; } for(int i=1;i<=q;i++) { scanf(" %c%d",&ch,&x); cz[i]=x;b[i]=(ch=='C'); if(b[i])fa[x]=x,cnt[x]++; } fa[1]=1;ff[1]=1; for(int i=2;i<=n;i++)if(!fa[i])fa[i]=ff[i]; for(int i=q;i;i--) { int k=cz[i]; if(b[i]&&!--cnt[k])fa[k]=ff[k]; if(!b[i])ans[++ct]=find(k); } for(int i=ct;i;i--)printf("%d\n",ans[i]); return 0; }