首页 > 其他分享 >左偏树/可合并堆

左偏树/可合并堆

时间:2023-12-01 11:56:24浏览次数:23  
标签:return int 合并 fa heap 左偏

左偏树/可合并堆 代码笔记

代码思路

主体部分:

合并堆(即merge函数)

大堆左偏,把小堆和大堆的右儿子合并。
感性理解:堆的形态将比较平衡。

辅助部分:

并查集维护堆关系

简化部分:

自定义数据类型(struct Bheap)

注意事项:

  1. 堆的最大数量是\(n+m\)

  2. 注意考虑堆被删空等细节情况(尤其是题目有要求时)

原理(极简)

堆\(+\)左偏 \(\to\) 距离小于\(\log_2{(n+1)}\)

代码注释

#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 2000006;
int n, cnt, fa[N]; // 堆的数量 
struct Bheap{
    int l, r, w, h; // 左儿子 右儿子 堆顶 堆高 
}heap[N]; // 堆 
bool del[N];

int merge(int a, int b){ // 合并堆 
    if(heap[a].w < heap[b].w) swap(a, b); // a.w >= b.w
    if(!a || !b) return a|b; // 边界情况
	// ↑不讨论的话会发生越界导致RE或者MLE 
    int merg = merge(heap[a].r, b); // 递归
    heap[a].r = merg; fa[heap[a].r] = a; // 更新右儿子 
    if(heap[heap[a].l].h < heap[heap[a].r].h)
        swap(heap[a].l, heap[a].r); // 更新左偏
    heap[a].h = heap[heap[a].r].h + 1; // 更新堆高 
    return a;
}

int find(int a){ // 路径压缩的并查集 
    if(a != fa[a]) fa[a] = find(fa[a]);
    return fa[a];
}

int main(){
    scanf("%d", &n);
    int k, x, y;
    for(int i = 1; i <= n; i++){
        scanf("%d", &k);
        if(k == 1){ // 新增堆 
            scanf("%d", &x); // x:v
            heap[++cnt] = (Bheap){0, 0, x, 1};
            fa[cnt] = cnt; del[cnt] = 0; continue;
        }
        if(k == 2){ // 合并堆 
            scanf("%d%d", &x, &y);
            if(del[x] && del[y]){ printf("-1\n"); continue; }
            if(del[x]){ printf("%d\n", heap[find(y)].w); continue; }
            if(del[y]){ printf("%d\n", heap[find(x)].w); continue; }
            // ↑有堆被删空的情况 ↓合并并输出新堆顶 
            x = find(x), y = find(y);
            if(x != y) fa[x] = fa[y] = merge(x, y);
            printf("%d\n", heap[fa[x]].w);
            continue;
        }
        if(k == 3){ // 删除堆顶 
            scanf("%d", &x);
            if(del[x]){ // 如果删空 
                printf("-1\n");
                continue;
            }
            x = find(x), del[x] = 1; // 删除堆顶 
            if(heap[x].l){ // 如果堆里还有元素 
                int l = heap[x].l, r = heap[x].r;
                heap[x].l = heap[x].r = 0;
                // ↑删除堆顶 ↓合并左右儿子为新堆 
                fa[x] = fa[l] = fa[r] = merge(l, r);
                printf("%d\n", heap[fa[l]].w);
                // ↑输出新堆顶 
				continue;
            } // ↓如果删空 
            printf("-1\n");
        }
    }
    return 0;
}

标签:return,int,合并,fa,heap,左偏
From: https://www.cnblogs.com/meteor2008/p/17869332.html

相关文章

  • Git合并时一些鲜为人知的坑
    1. 反复解决同一个冲突最常见的原因:  多人团队中开启了rebase,对commit顺序造成破坏,使得merge其他分支时可能找不到原始commitid的关联信息,就需要重新merge conflicts.  2.明明合并完了,又让从头合并当然这和用rebase有关的,关键是已经解决了冲突,为啥还让从头再来一次。......
  • 使用C#将几个Excel文件合并去重分类
    需要将几个Excel表格里面的数据去重,然后将每个站点的数据另存为一张Sheet上。几个表格如下所示: 实现效果如下所示: 具体实现需要使用EPPlus操作Excel安装EPPlus如下所示: 为了更好的演示与说明,把步骤进行了拆分,先导入Excel数据,再去重,再进行数据分类,最后再导出为Excel......
  • margin穿透/传递/合并/折叠 多层 爷孙
    https://codepen.io/rhdom/pen/vYbarpm如这个代码所示<divclass="show"> <div>  <h2>crystal</h2> </div></div> <divdata-v-3151e59a=""class="form-widget-list"> <divdata-v-6f598f02=&......
  • 倾斜摄影三维模型的根节点合并的轻量化技术方法分析
    倾斜摄影三维模型的根节点合并的轻量化技术方法分析 倾斜摄影三维模型的根节点合并是一种轻量化技术,旨在减小模型数据的大小,提高渲染效率和加载速度。在本文中,我们将探讨关于倾斜摄影三维模型根节点合并的轻量化技术方法。1、LOD(层次细节)技术:LOD是一种常用的轻量化技术,通过......
  • Excel合并单元格的缺点解决方式
    背景99%的人在创建表格的一个标题,都喜欢使用合并单元格的功能但是由于使用Excel的合并单元格,在数据分析统计的时候出现了一些问题复制粘贴数据时,由于有合并单元格,不能直接复制粘贴移动整列的位置,不能快速移动使用VLOOKUP函数时,无法直接选中列区域,只能手动选中单元格区域......
  • P1090 [NOI洛谷P2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G
    可以用堆来实现,或者更简单一点的优先队列优先队列:#include<queue>priority_queue<int,vector<int>,greater<int>>q;因为每次合并后,最小的两个值都会更新,所以可以很好的利用优先队列内元素有序的特点,减少因反复排序带来的时间复杂度;一开始我用STL自带的排序sort,报了5个TLE,后来意......
  • Django - 多条queryset合并,并排序
     fromitertoolsimportchainfromoperatorimportattrgetter#拿到多条querysetqueryset1=model.objects.filter(status=1).all()queryset2=model.objects.filter(status=2).all()#将上面两组查询结果合并,并设置排序方式:-create_timenew_queryset=sorted......
  • el-table列相同数据合并行
    1、效果2、数据[{"date":"2016-05-02","name":"王小虎","address":"上海市普陀区金沙江路1518弄"},{"date":"2016-05-04","name"......
  • SQL JOIN 子句:合并多个表中相关行的完整指南
    SQLJOINJOIN子句用于基于它们之间的相关列合并来自两个或更多表的行。让我们看一下“Orders”表的一部分选择:OrderIDCustomerIDOrderDate1030821996-09-1810309371996-09-1910310771996-09-20然后,看一下“Customers”表的一部分选择:CustomerID......
  • P1090 [NOIP2004 提高组] 合并果子
    原题链接题解每次从所有果子堆中选重量最小的两堆并累加,观察到只需要找出最小因此考虑用堆代码#include<bits/stdc++.h>usingnamespacestd;intpile[10005]={0};intlen=0;voidin(intx){pile[++len]=x;intnow=len;while(pile[now]<pile[now/2]......