解析
看起来就是左偏树的基本操作啊…
然而就是调不过去
吐了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_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
dis[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;
}