44 分。
现在想到的问题有:用并查集维护元素位于的堆以及求最小后应该把最小元素的右儿子“平移”到它本身的位置。
请问各位大佬还有没有其它可能的问题,最好能帮我调出来代码(当然没有我也不会有强求)。
代码:
#include<bits/stdc++.h>
//#define int long long
using namespace std;
int cnt,root[1000005];
struct Node
{
int ls,rs,key,pri,sz;
}t[1000005];
bitset<1000005> bs;
int build(int x)
{
t[++cnt].sz=1;
t[cnt].ls=t[cnt].rs=0;
t[cnt].key=x;
t[cnt].pri=rand()*rand();
return cnt;
}
void update(int u)
{
t[u].sz=t[t[u].ls].sz+t[t[u].rs].sz+1;
}
void split(int u,int x,int& L,int& R)
{
if(!u)
{
L=R=0;
return ;
}
if(t[u].key<=x)
{
L=u;
split(t[u].rs,x,t[u].rs,R);
}
else
{
R=u;
split(t[u].ls,x,L,t[u].ls);
}
update(u);
}
int merge(int L,int R)
{
if(L==0||R==0)return L+R;
int l,r;
if(t[L].pri<=t[R].pri)
{
split(R,t[L].key,l,r);
t[L].ls=merge(t[L].ls,l);
t[L].rs=merge(t[L].rs,r);
update(L);
return L;
}
split(L,t[R].key,l,r);
t[R].ls=merge(t[R].ls,l);
t[R].rs=merge(t[R].rs,r);
update(R);
return R;
}
int _kth(int u,int k)
{
if(k==t[t[u].ls].sz+1)return u;
if(k<=t[t[u].ls].sz)return _kth(t[u].ls,k);
if(k>t[t[u].ls].sz)return _kth(t[u].rs,k-t[t[u].ls].sz-1);
}
int kth(int u,int k){return t[_kth(u,k)].key;}
int n,i,m,op,x,y;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
srand(time(NULL));
cin>>n>>m;
for(i=1;i<=n;i++)
{
cin>>x;
root[i]=build(x);
}
while(m--)
{
cin>>op>>x;
if(op==1)
{
cin>>y;
root[x]=root[y]=merge(root[x],root[y]);
}
else
{
if(bs[x])
{
cout<<-1<<endl;
continue;
}
int L,R;
split(root[x],kth(root[x],1),L,R);
cout<<t[L].key<<endl;
bs[L]=1;
root[x]=R;
}
}
return 0;
}
玄关