解析
看起来就是左偏树的基本操作啊…
然而就是调不过去
吐了qwq
参考了望月大神的实现
感觉清晰的多
就定义并查集维护的是每个点所在的堆的根节点
一下子少了很多恶心的套娃
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
const int N=4e6+100;
const double eps=1e-9;
inline ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;
}
int n,m,w;
ll k;
int ls[N],rs[N],dis[N],tot,f[N],rt[N];
ll val[N];int bel[N],vis[N];
int find(int x){return x==bel[x]?x:bel[x]=find(bel[x]);}inline int New(ll v){++tot;ls[tot]=rs[tot]=0;f[tot]=0;dis[tot]=0;val[tot]=v;return tot;
}
inline void pushup(int x){if(dis[rs[x]]>dis[ls[x]]) swap(ls[x],rs[x]);dis[x]=dis[rs[x]]+1;return;
}
int merge(int u,int v){if(!u||!v){return u|v;}if(val[u]<val[v]||(val[u]==val[v]&&u>v)) swap(u,v);rs[u]=merge(rs[u],v);pushup(u);bel[ls[u]]=bel[rs[u]]=bel[u]=u;return u;
}void del(int x){if(vis[x]) return;vis[x]=1;val[x]=0;int o=merge(ls[x],rs[x]);ls[x]=rs[x]=0;merge(find(x),o);return;
}
void Merge(int u,int v){u=find(u),v=find(v);if(u==v) return;merge(u,v);return;
}
void jianshao(int x,int w){x=find(x);if(val[x]<=w){del(x);return;}int o=x,oo=merge(ls[x],rs[x]);ls[o]=rs[o]=0;val[o]-=w;ls[o]=rs[o]=0;merge(o,oo);return;
}int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifdis[0]=-1;int T=read();w=read();k=read();while(T--){tot=0;memset(vis,0,sizeof(vis));n=read();m=read();for(int i=1;i<=n;i++){New(read());bel[i]=i;}for(int i=1;i<=m;i++){int op=read();if(op==2) del(read());else if(op==3){int a=read(),b=read();jianshao(a,b);}else{Merge(read(),read());}}ll res(0),mx(0);for(int i=1;i<=n;i++){if(find(i)!=i) continue;res+=val[i];mx=max(mx,val[i]);}if(w==2) res-=mx;else if(w==3) res+=mx;if(res>k) printf("Hell "); else if(res) printf("Heaven ");else printf("Gensokyo ");printf("%lld\n",res);}return 0;
}