最近一直在学图论,然后吧,由于学的东西实在是太多太杂了,加上蒟蒻本蒻又经常颓,所以落了好多好多板子题的整理没写啊嘤嘤嘤,不过把这些东西学的差不多了,再一块写个整理,其实感觉还不错?????也算是很神奇吧,大概就是知识的积淀这一块有了一点用

好了,话不多说,我们来进入正题

P3378 【模板】堆

我们从板子题入手,慢慢的了解堆(其实是自己巩固而已QWQ)

这里我们学习的堆其实是二叉堆,算是比较狭义的一种定义吧,首先,

堆是一种特殊的二叉树,而且是完全二叉树

为什么我们接触到的比较早的数据结构是堆呢?

其实有这么几个原因:

1.因为堆是一颗完全二叉树,所以在父亲和儿子方面,就完全不需要结构体存树,而是严格按照完全二叉树的定义来就可以

一棵树上的一个节点i,他的儿子是i*2和i*2+1,他的父亲是i/2(此处为整除)

所以处理的时候就很方便啊。

2.c++自带的STL对于堆非常友好,基本上随便写几个STL就能构建一个堆,即使是手写,大约时间也就是十分钟左右,并不是太慢。

3.堆的应用不少,比如堆排序,以及了解一种数据结构,为将来学习可并堆,斐波那契堆打下坚实基础,而且能优化dijkstra(图论).

下面来讲一讲堆的一些基本操作步骤

插入(大雾

我们要对堆插入一个元素,但是并不是扔进去,让尾指针++就完事了,我们还得对堆的正确性进行维护。

来说一下思想,对于添加进来的元素,设其位置为now,那么他爹就是now/2(now>>1  位运算更快哦)

只要比较二者大小,如果新元素更小,那么就交换即可,否则意味着合法,我们直接退出循环就可以,循环的终止条件就是now!=1(因为当now==1时,它已经是堆首元素,没爹。。。。多苦的一孩子(大雾)

来看代码

inline void add(int x)
{
Heap[++cnt] = x;//这里小小的压了一下行
int now = cnt;
while (now!=)
{
if (Heap[now] < Heap[now >> ])
swap(Heap[now], Heap[now >> ]),now>>=;
else
break;
}
}

弹出

这个也要分为两种,一种是弹出堆首元素,另一种是弹出任意位置的元素(这种一般与寻找元素相结合,考察对DFS,BFS之类的搜索方法的能力)

先看弹出堆首元素,

想要弹出的话,我们就把最小值修改为INF(我比较喜欢1e9),然后和之前相反,向下比较直到找到合适为止为止。

具体讲一讲

因为小根堆的要求是所有根节点都得比他孩子小,所以我们定义首节点的位置为root=1,因为已经置成INF了,所以我们向下开始比较;

先让两个孩子比,最小的那个再和root比,如果比root小,那么就交换二者,否则符合条件就直接退出循环,这里的循环终止条件是   root << 1 <= cnt,也就是说root的儿子已经比当前的堆的长度大了,也就是不存在儿子了

但是这种方法其实不是很好啊,因为你排到最后,最底下就一大堆INF,难看的要死还占空间,倒不如直接交换首元素和尾元素,然后直接把尾指针减一就可以,这样的话最小值就被删除了,之后进行一下动态维护就可以。

来看代码

inline void pop()
{
Heap[] = Heap[cnt--];
int root = ;
while (root << <= cnt)
{
int son;
if ((root << ) + > cnt ||
Heap[root << ] < Heap[(root << ) + ])
{
son = root << ;
}
else
son = (root << ) + ;
if (Heap[son] > Heap[root])
break;
swap(Heap[root], Heap[son]);
root = son;
}
}

输出堆首元素

这东西其实没啥好讲的,因为堆首元素就肯定是Heap[1]嘛,知道就行,然后就可以输出了,因为不对堆中元素进行移动和修改,是不影响堆的合法性的。

这些都看的差不多了,就直接略微修改,板子题就切掉啦

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstdio>
using namespace std;
const int INF = ;
int n, a, b, Heap[], cnt = ;
inline void add(int x)
{
Heap[++cnt] = x;
int now = cnt;
while (now!=)
{
if (Heap[now] < Heap[now >> ])
swap(Heap[now], Heap[now >> ]),now>>=;
else
break;
}
}
inline void print()
{
printf("%d\n", Heap[]);
}
inline void pop()
{
Heap[] = Heap[cnt--];
int root = ;
while (root << <= cnt)
{
int son;
if ((root << ) + > cnt ||
Heap[root << ] < Heap[(root << ) + ])
{
son = root << ;
}
else
son = (root << ) + ;
if (Heap[son] > Heap[root])
break;
swap(Heap[root], Heap[son]);
root = son;
}
}
int main()
{
scanf("%d", &n);
for (int i = ; i <= n; ++i)
{
scanf("%d", &a);
if (a == )
{
scanf("%d", &b);
add(b);
}
if (a == )
print();
if (a == )
pop();
}
return ;
}

还是肥肠感谢gh神仙的热心帮忙啊,,,,QWQ一个板子题交了三四遍才过,真的是太辣鸡了

看完板子题,我们来看看合并果子这个题

P1090 合并果子

这个题在学完堆之后就好做多了,不过蒟蒻我很早以前做的时候是用dp加快排做的,那叫一个惨不忍睹啊,,,,,,,,连个样例都没过,所以干脆也就没有提交记录了

但是我们要分析分析,为什么这种算法会TLE

思考一下,我们对于,每一堆果子的个数进行排序,这样的话,先合并前两个果子,看似没什么问题,但是当你合并完了之后,你又得干啥呢???

我当时就傻乎乎的又用sort,然后就连本地编译都会超时,我们分析一下时间复杂度,其实就是O(nlongn+(n-1)log(n-1)+(n-2)log(n-2)+.....+log 1)

这样的话就肥肠慢了啊,因为每一次快排都是遍历了所有的数,但是其实很大一部分都是有序的,所以快排也没什么用,反而浪费时间。

那么用堆解决就没有任何问题了

每次合并前两个小的集合,然后把合并完的集合加到ans中,再扔回堆进行维护,这道题就做完啦

上代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,ans,Heap[],num,cnt=,sum;
inline void add(int x)
{
Heap[++cnt] = x;
int now = cnt;
while (now!=)
{
if (Heap[now] < Heap[now >> ])
swap(Heap[now], Heap[now >> ]),now>>=;
else
break;
}
}
inline void pop()
{
Heap[] = Heap[cnt--];
int root = ;
while (root << <= cnt)
{
int son;
if ((root << ) + > cnt ||
Heap[root << ] < Heap[(root << ) + ])
{
son = root << ;
}
else
son = (root << ) + ;
if (Heap[son] > Heap[root])
break;
swap(Heap[root], Heap[son]);
root = son;
}
}
int main()
{ scanf("%d",&n);
for(int i=;i<=n;++i)
{
scanf("%d",&num);
add(num);
}
while(cnt>=)
{
sum+=Heap[];
pop();
sum+=Heap[];
pop();
ans+=sum;
add(sum);
sum=;
}
printf("%d",ans);
return ;
}

想看堆排的同学看这里

堆以及一些用法 QWQ这是写得最认真的板子题的更多相关文章

  1. IOS Quartz 各种绘制图形用法---实现画图片、写文字、画线、椭圆、矩形、棱形等

    // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affec ...

  2. spm使用之六安装别人写好的spm文档主题模板

    上回说到有个nico-one的文档主题模板, https://github.com/lepture/nico-one 把他可以下载了, 放到 C:\Documents and Settings\Adm ...

  3. 在平衡树的海洋中畅游(四)——FHQ Treap

    Preface 关于那些比较基础的平衡树我想我之前已经介绍的已经挺多了. 但是像Treap,Splay这样的旋转平衡树码亮太大,而像替罪羊树这样的重量平衡树却没有什么实际意义. 然而类似于SBT,AV ...

  4. Luogu4081 USACO17DEC Standing Out from the Herd(广义后缀自动机)

    建出广义SAM,通过parent树对每个节点求出其是否仅被一个子串包含及被哪个包含. 写了无数个sam板子题一点意思都没啊 #include<bits/stdc++.h> using na ...

  5. 洛谷$P2168\ [NOI2015]$荷马史诗 贪心

    正解:贪心 解题报告: 传送门$QwQ$ 昂这个就哈夫曼树板子题鸭$QwQ$,只是从二叉变成多叉了$QwQ$ 考虑用类似合并果子的方法?就从两个变成$k$个了嘛,一样的鸭,然后就做完了$QwQ$ 注意 ...

  6. 洛谷$P$4137 $Rmq\ Problem / mex$ 主席树

    正解:主席树 解题报告: 传送门$QwQ$ 本来以为是道入门无脑板子题,,,然后康了眼数据范围发现并没有我想像的那么简单昂$kk$ 这时候看到$n$的范围不大,显然考虑离散化?但是又感觉似乎布星?因为 ...

  7. 自己动手写CPU——寄存器堆、数据存储器(基于FPGA与Verilog)

    上一篇写的是基本的设计方案,由于考研复习很忙,不知道下一次什么时候才能打开博客,今天就再写一篇.写一写CPU中涉及到RAM的部件,如寄存器堆.数据存储器等. 大家应该在大一刚接触到计算机的时候就知道R ...

  8. 如何获取JVM堆转储文件

    堆转储是诊断与内存相关的问题(例如内存泄漏缓慢,垃圾回收问题和 java.lang.OutOfMemoryError.它们也是优化内存消耗的重要工具. 有很多很不错的的工具,例如Eclipse MAT ...

  9. 【转载】Delphi异常处理try except语句和try finally语句用法以及区别

    Delphi异常处理try except语句和try finally语句用法以及区别 一直写程序都没管他们,也尽量很少用,今天终于想把他给弄个明白,在网上找来,记下!主要是前面小部分,后面的是详细说明 ...

随机推荐

  1. centOS7下Spark安装配置

    环境说明: 操作系统: centos7 64位 3台 centos7-1 192.168.190.130 master centos7-2 192.168.190.129 slave1 centos7 ...

  2. 都 9012了,该选择 Angular、React,还是Vue?

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 尽管 Web开发的典型应用场景除了将服务器用作平台.浏览器用作客户端之外,几乎很少活跃于其他业务领域,但不可 ...

  3. Java:API文档;文档注释中的javadoc标记;官方API;自己动手给项目建一个API文档

    1.什么是API文档 在Java语言中有3种注释 //单行注释 /* 多行注释 */ /** * 文档注释 */ API(应用程序接口)文档就是用javadoc命令提取文档注释生成的,html格式,用 ...

  4. 网站升级HTTPS后WebSocket不能连接的问题

    一.前端代码 var socket = new WebSocket("wss://www.smcic.cn/wss/"); 注意点: 如果网站使用HTTPS,WebSocket必须 ...

  5. 网站通信协议升级到HTTPS&HTTP2

    为何要升级到HTTPS和HTTP2? http://baijiahao.baidu.com/s?id=1602041305989767011&wfr=spider&for=pc htt ...

  6. CodeBlocks卸载后重装 编译c文件提示错误信息“No such file or directory”

    编译最简单的helloworld程序,提示第一行#include<stdio.h> 找不到头文件. 解决方法: 再次卸载CodeBlocks后,将之前的配置文件删除. 路径:C:\User ...

  7. java基础-01基本概念

    java的特点 跨平台 所谓的平台,我们可以理解为操作系统. 大部分语言是不能跨平台的,比如c语言的程序在windows和linux上需要编写不同的代码. java程序是运行在JVM(Java Vir ...

  8. Django使用models建表的一些另类功能

    当我们对某个表需要在创建时,给他绑定一个随机的id,那么我们怎么做呢? 当创建一个用户时执行的为save方法,所以通过下面的 super(UserInfo, self).save(*args, **k ...

  9. 使用sqlserver 链接远程服务器进行查询

    --创建链接服务器 exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' exec sp_addlinkedsrvlogi ...

  10. TOMCAT原理详解及请求过程(转载)

    转自https://www.cnblogs.com/hggen/p/6264475.html TOMCAT原理详解及请求过程 Tomcat: Tomcat是一个JSP/Servlet容器.其作为Ser ...