BZOJ 1455 罗马游戏 ——左偏树
【题目分析】
左偏树的模板题目,大概就是尽量维护树的深度保持平衡,以及尽可能的快速合并的一种堆。
感觉和启发式合并基本相同。
其实并没有快很多。
本人的左偏树代码自带大常数,借鉴请慎重
【代码】
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <set> #include <map> #include <string> #include <algorithm> #include <vector> #include <iostream> #include <queue> using namespace std; #define maxn 1000005 int read() { int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } int fa[maxn],v[maxn]; int n,q,l[maxn],r[maxn],die[maxn],d[maxn]; char opt[11]; int gf(int k) { if (fa[k]==k) return k; else return fa[k]=gf(fa[k]); } int merge(int x,int y) { if (!(x*y)) return x+y; if (v[x]>v[y]) swap(x,y); r[x]=merge(r[x],y); if (d[l[x]]<d[r[x]]) swap(l[x],r[x]); d[x]=d[r[x]]+1; return x; } int main() { n=read(); for (int i=1;i<=n;++i) v[i]=read(),fa[i]=i; q=read(); while (q--) { scanf("%s",opt); if (opt[0]=='M') { int x=read(),y=read(); if (die[x]||die[y]) continue; int fx=gf(x),fy=gf(y); if (fx!=fy) fa[fx]=fa[fy]=merge(fx,fy); } else { int x=read(); if (die[x]) { printf("0\n"); continue; } else { int fx=gf(x); die[fx]=1; printf("%d\n",v[fx]); int tmp=merge(l[fx],r[fx]); fa[fx]=fa[tmp]=tmp; } } } }