2 条题解

  • 0
    @ 2026-7-29 1:12:33
    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e6+10;
    #define pii pair<int,int>
    #define ft first
    #define sd second
    priority_queue<pii,vector<pii>,greater<pii>> Q[N];
    int fa[N],del[N];
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    void merge(int x,int y)
    {
    	if(del[x] || del[y]) return;
    	int fx=find(x),fy=find(y);
    	if(fx==fy) return;
    	if(Q[fx].size()<Q[fy].size())swap(fx,fy);
    	fa[fy]=fx;
    	while(!Q[fy].empty())
    	{
    		Q[fx].push(Q[fy].top());
    		Q[fy].pop();
    	}
    }
    int query(int x)
    {
    	if(del[x]) return 0;
    	int fx=find(x); 
    	pii ans=Q[fx].top(); Q[fx].pop();
    	del[ans.sd]=1;
    	return ans.ft;
    }
    int main()
    {
    	int n,m;scanf("%d",&n);
    	for(int i=1,x;i<=n;i++)
    	{
    		scanf("%d",&x);
    		Q[i].push({x,i});
    		fa[i]=i,del[i]=0;
    	}
    	int x,y;char op[5];
        scanf("%d",&m);
    	while(m--)
    	{
    		scanf("%s",op);
    		if(op[0]=='M') 
    		{
    			scanf("%d%d",&x,&y);
    			merge(x,y);
    		}
    		if(op[0]=='K')
    		{
    			scanf("%d",&x);
    			printf("%d\n",query(x));
    		}
    	}
    	return 0;
    }
    
    
    • 0
      @ 2025-10-8 17:03:59

      C16【模板】左偏树(可并堆)

      #include <iostream>
      #include <cstring>
      #include <algorithm>
      using namespace std;
      
      const int N=1e6+10;
      int v[N],lc[N],rc[N],dis[N]; //左偏树
      int fa[N]; //并查集
      
      int find(int x){ //并查集找根
        return x==fa[x] ? x : fa[x]=find(fa[x]);
      }
      int merge(int x,int y){
        if(!x||!y) return x+y; //若一个堆为空则返回另一个堆
        if(v[x]==v[y] ? x>y : v[x]>v[y]) swap(x,y); //取小值做根
        rc[x]=merge(rc[x],y); //递归合并右儿子与另一个堆
        
        if(dis[lc[x]]<dis[rc[x]]) swap(lc[x],rc[x]); //维护左偏性
        dis[x]=dis[rc[x]]+1;  //更新dis
        return x; //返回合并后的根
      }
      int main(){
        int n,m; scanf("%d",&n);
        for(int i=1; i<=n; i++) scanf("%d",&v[i]);
        for(int i=1; i<=n; i++) fa[i]=i;
        dis[0]=-1; //空节点的dis初始化
        scanf("%d",&m);
        for(int x,y; m; m--){
          char op[5];scanf("%s",&op);
          if(op[0]=='M'){ //合并堆
            scanf("%d%d",&x,&y);
            if(v[x]==-1 || v[y]==-1) continue;
            x=find(x), y=find(y);
            if(x!=y) fa[x]=fa[y]=merge(x,y);
          }
          else{ //删除堆顶
            scanf("%d",&x);
            if(v[x]==-1){printf("0\n"); continue;}
            x=find(x);
            printf("%d\n",v[x]);
            v[x]=-1; //删除标记
            fa[lc[x]]=fa[rc[x]]=fa[x]=merge(lc[x],rc[x]);
          }
        }
      }
      
      • 1

      C16【模板】左偏树(可并堆)罗马游戏

      信息

      ID
      3108
      时间
      1000ms
      内存
      128MiB
      难度
      10
      标签
      递交数
      7
      已通过
      2
      上传者