bzoj 4551: [Tjoi2016&Heoi2016]树 并查集

来源:互联网 发布:网络机顶盒刷机通用版 编辑:程序博客网 时间:2024/06/08 12:17

题意:有一棵树,一开始根节点是黑色的,其余节点都是白色的。要求资瓷两个操作:

给某个节点变成黑色

查询离某个节点最近的祖先


分析:一开始往各种数据结构和神奇的算法上面去想但都没卵用,也想过离线,但感觉貌似不行就pass了。结果正解真的是离线搞……

以后有想法后一定要仔细想清楚是否能行。

正解其实就是从后往前搞然后用并查集维护一下就好了。

一次AC不解释


代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define N 100005using namespace std;int n,m,f[N],fa[N],ans[N],x[N],last[N],cnt,tag[N];char ch[N][2];struct edge{int to,next;}e[N*2];void insert(int u,int v){e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;}int find(int x){if (f[x]==x) return x;f[x]=find(f[x]);return f[x];}void dfs(int x,int p){if (x!=p) f[find(x)]=find(p);for (int i=last[x];i;i=e[i].next){if (e[i].to==fa[x]) continue;fa[e[i].to]=x;if (tag[e[i].to]) dfs(e[i].to,e[i].to);else dfs(e[i].to,p);}}int main(){scanf("%d%d",&n,&m);for (int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);insert(u,v);}tag[1]++;for (int i=1;i<=m;i++){scanf("%s%d",&ch[i],&x[i]);if (ch[i][0]=='C') tag[x[i]]++;}for (int i=1;i<=n;i++)f[i]=i;dfs(1,1);for (int i=m;i>=1;i--)if (ch[i][0]=='C'){tag[x[i]]--;if (!tag[x[i]]) f[find(x[i])]=find(fa[x[i]]);}else ans[i]=find(x[i]);for (int i=1;i<=m;i++)if (ch[i][0]=='Q') printf("%d\n",ans[i]);return 0;}


0 0