题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1455
还是对并查集的 rt 不太熟悉...
注意删去一个堆顶后把它的 fa (rt) 改成儿子合成的新堆顶,这样路径压缩也没有错了。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int const maxn=1e6+5; int n,m,fa[maxn],ls[maxn],rs[maxn],a[maxn],dis[maxn]; bool vis[maxn]; char c[5]; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return ret*f; } int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} int merge(int x,int y) { if(!x||!y)return x+y; if(a[x]>a[y])swap(x,y); rs[x]=merge(rs[x],y); fa[rs[x]]=x; if(dis[ls[x]]<dis[rs[x]])swap(ls[x],rs[x]); if(rs[x])dis[x]=dis[rs[x]]+1; else dis[x]=0; return x; } void del(int x) { fa[ls[x]]=ls[x]; fa[rs[x]]=rs[x];//! fa[x]=merge(ls[x],rs[x]);//改变 fa[x]! ls[x]=rs[x]=dis[x]=0; vis[x]=1; } int main() { n=rd(); for(int i=1;i<=n;i++)a[i]=rd(),fa[i]=i; m=rd(); for(int i=1,x,y;i<=m;i++) { scanf("%s",c); if(c[0]=='M') { x=rd(); y=rd(); if(vis[x]||vis[y])continue; int u=find(x),v=find(y); if(u==v)continue;//!!! merge(u,v); } else { x=rd(); if(vis[x]){printf("0 "); continue;} printf("%d ",a[find(x)]),del(find(x)); } } return 0; }