左偏樹模板
阿新 • • 發佈:2020-08-22
題目
測試題目傳送門
Code
//By zuiyumeng #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define Re register #define Ms(a,b) memset((a),(b),sizeof(a)) #define Fo(i,a,b) for(Re int i=(a),_=(b);i<=_;i++) #define Ro(i,a,b) for(Re int i=(b),_=(a);i>=_;i--) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();} while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar(); return x*f; } const int N=1e5+10; int n,m; int fa[N],nd[N][2],dis[N],val[N]; // bool deld[N]; //是否刪除過 1表示已刪除 int getro(int x) {return fa[x]=fa[x]==x?x:getro(fa[x]);} #define ls nd[x][0] #define rs nd[x][1] int merge(int x,int y) { if(!x||!y) return x+y; if(val[x]>val[y]) swap(x,y); if(val[x]==val[y]&&x>y) swap(x,y);//題目要求:最小值相同時優先刪除編號最小的 fa[rs=merge(rs,y)]=x; if(dis[ls]<dis[rs]) swap(ls,rs); dis[x]=dis[rs]+1; return x; } int main() { n=read(); m=read(); dis[0]=-1; //代表所有空點的dis值為-1,因為nd[]初始全為0 Fo(i,1,n) val[i]=read(),fa[i]=i; Fo(i,1,m) { int opt=read(); if(opt==1) { int x=read(),y=read(); if(deld[x]||deld[y]) continue; int rx=getro(x),ry=getro(y); if(rx==ry) continue; fa[rx]=fa[ry]=merge(rx,ry); } else { int x=read(); if(deld[x]) {cout<<"-1"<<endl;continue;} x=getro(x); cout<<val[x]<<endl; deld[x]=1; //簡單的刪除操作 fa[x]=fa[ls]=fa[rs]=merge(ls,rs);//由於使用了路徑壓縮,有很多點fa[]值為x,所以不如直接fa[x]=新根 } } return 0; }