洛谷3377
推荐一篇好的博文
dis表示该点到最近叶子节点经过的路
#include<cstdio> #include<cctype> #define maxn 100001 using namespace std; int n,m,val[maxn],dis[maxn],f[maxn],tr[maxn][2]; inline void swap(int &x,int &y){int t=x;x=y;y=t;} inline void read(int &x){ char ch=getchar();x=0; while(!isdigit(ch))ch=getchar(); while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} } //一定要注意这里findfa不能过程中合并,否则删点时会出问题 inline int findfa(int x){ while(f[x])x=f[x];return x; } inline int merge(int x,int y){ if(x==0||y==0)return x+y; if(val[x]>val[y]||(val[x]==val[y]&&x>y))swap(x,y); tr[x][1]=merge(tr[x][1],y); f[tr[x][1]]=x; if(dis[tr[x][0]]<dis[tr[x][1]])swap(tr[x][0],tr[x][1]); dis[x]=dis[tr[x][1]]+1; } inline void pop(int x){ val[x]=-1; f[tr[x][0]]=f[tr[x][1]]=0; merge(tr[x][0],tr[x][1]); } int main(){ read(n);read(m); dis[0]=-1; for(int i=1;i<=n;i++)read(val[i]); for(int i=1;i<=m;i++){ int ty;read(ty); if(ty==1){ int x,y; read(x);read(y); if(val[x]==-1||val[y]==-1)continue; int fx=findfa(x),fy=findfa(y); if(fx==fy)continue; merge(fx,fy);printf("%d ",f[2]); }else{ int x;read(x); if(val[x]==-1)puts("-1"); else{ int y=findfa(x); printf("%d\n",val[y]); pop(y); } } } }