可并堆神秘Treap做法求捞(玄关)
查看原帖
可并堆神秘Treap做法求捞(玄关)
782495
Bai_R_X楼主2025/7/21 22:23

4444 分。

现在想到的问题有:用并查集维护元素位于的堆以及求最小后应该把最小元素的右儿子“平移”到它本身的位置。

请问各位大佬还有没有其它可能的问题,最好能帮我调出来代码(当然没有我也不会有强求)。

代码:

#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;
}

玄关

2025/7/21 22:23
加载中...