@[peterha](/user/239895)
老哥,你 h 是并查集吧,你用并查集指向当前合并以后分数最低的士兵,你确定这样并查集不会出锅?
不要随便玩并查集啊……
我现在帮你改了下,已经能过了,做法是并查集正常维护,然后把左偏树的根塞在并查集的根上,具体的是那个 st 数组。
```cpp
#include<bits/stdc++.h>
using namespace std;
int n,m,h[1000003];
bool f[1000003];
struct node{
int nm,l,r,ds;
}t[1000003];
int st[1000003];
int fd(int a){ //并查集路径压缩
if(h[a]!=a) h[a]=fd(h[a]);
return h[a];
}
int hb(int x,int y){ //合并操作
if(!x||!y) return x+y;
if(t[x].nm>t[y].nm) swap(x,y);
t[x].r=hb(t[x].r,y);
if(t[t[x].l].ds<t[t[x].r].ds)
swap(t[x].l,t[x].r);
t[x].ds=t[t[x].r].ds+1;
return x;
}
int main(){
scanf("%d",&n);
t[0].ds=-1;
for(int i=1;i<=n;++i)
scanf("%d",&t[i].nm),h[i]=i,st[i]=i;
scanf("%d",&m);
char op=0;
int x=0,y=0;
for(int i=1;i<=m;++i){
for(cin>>op;op!='M'&&op!='K';cin>>op);
scanf("%d",&x);
if(op=='M'){ //操作一,合并
scanf("%d",&y);
if(f[x]||f[y]) continue;
int a=fd(x),b=fd(y);
if(a!=b) h[a]=b,st[b]=hb(st[b],st[a]);
}
else if(op=='K'){ //操作二,删除
if(f[x]){
printf("0\n");
continue;
}
x=fd(x);int now=st[x];f[now]=true;
printf("%d\n",t[now].nm);
st[x]=hb(t[now].l,t[now].r);
// t[now].l=t[now].r=t[now].ds=0;
}
}
return 0;
}
```
by zjjws @ 2021-04-14 07:40:05
@[zjjws](/user/73551) 应该不用那样大改吧?其实只是并查集的合并写错了:
```cpp
if(a!=b) h[x]=h[y]=hb(x,y);
```
```cpp
if(a!=b) h[a]=h[b]=hb(a,b);
```
by Legitimity @ 2021-04-14 21:27:32
@[zjjws](/user/73551) 大感谢,懂了
by Yusani_huh @ 2021-04-14 22:56:35
@[win10](/user/241977)
az
我不清楚有没有锅但是这俩东西混一起确实有点恶心。这种写法很危,我猜测在有改点权的时候会挂掉。
by zjjws @ 2021-04-15 07:31:54
@[Legitimity](/user/241977) 感谢!
by sleeping_crawlers @ 2022-03-28 14:17:38