左偏树
https://www.luogu.org/problem/P3377
知识点:1.并查集路径压缩:注意赋值
2.顺带讲一下,这题裸的并查集是过不了的,要用路径压缩,但是路径压缩会破坏树的性质,所以在删根节点的时候,记得把根节点的父亲指向新的根节点
#include <bits/stdc++.h> #define N 100010 using namespace std; int ch[N][2],val[N],dis[N],f[N],n,m; 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); ch[x][1] = merge(ch[x][1],y); if (dis[ch[x][0]] < dis[ch[x][1]]) swap(ch[x][0],ch[x][1]); dis[x] = dis[ch[x][1]] + 1; f[ch[x][1]] = f[ch[x][0]] = x; return x; } int getf(int x) { if(f[x] == x)return x; else return f[x] = getf(f[x]); } void pop(int x) { val[x] = -1; f[ch[x][0]] = ch[x][0]; f[ch[x][1]] = ch[x][1]; f[x] = merge(ch[x][0],ch[x][1]); } int main() { scanf("%d%d",&n,&m); dis[0] = -1; for(int i = 1;i <= n;i++) scanf("%d",&val[i]); for(int i = 1;i <= n;i++) f[i] = i; int opt,x,y; while(m--) { scanf("%d",&opt); if (opt == 1) { scanf("%d%d",&x,&y); if (val[x] == -1 || val[y] == -1) continue; if (x == y) continue; int fx = getf(x),fy = getf(y); merge(fx,fy); } else { scanf("%d",&x); if (val[x] == -1) puts("-1"); else { int z = getf(x); printf("%d\n",val[z]); pop(z); } } } return 0; }