堆的五个基本操作:

1.在集合中插入一个数      heap[++size]=x  ;  up[size]

2.求集合当中的最小值      heap[1]

3.删除最小值                    heap[1]=heap[size]  ;  size--  ;  down(1)

4.删除任意一元素             heap[k]=heap[size]  ;  size--  ;  down(k)  ;  up(k)

5.修改任一元素                 heap[k]=x  ;  down(k)  ;  up(k)

p3378[模板]堆

题目描述

给定一个数列,初始为空,请支持下面三种操作:

  1. 给定一个整数 x,请将 x 加入到数列中。
  2. 输出数列中最小的数。
  3. 删除数列中最小的数(如果有多个数最小,只删除 1 个)

符合模板中的1.2.3操作

输入格式

第一行是一个整数,表示操作的次数 n。
接下来 n 行,每行表示一次操作。每行首先有一个整数 op 表示操作类型。

  • 若 op=1,则后面有一个整数 xxx,表示要将 xxx 加入数列。
  • 若 op=2,则表示要求输出数列中的最小数。
  • 若 op=3,则表示删除数列中的最小数。如果有多个数最小,只删除 1 个。

输出格式

对于每个操作 2,输出一行一个整数表示答案。

输入输出样例

输入 #1复制

5
1 2
1 5
2
3
2

输出 #1复制

2
5

说明/提示

数据规模与约定

  • 对于 30%的数据,保证n<=15
  • 对于70%的数据,保证n<10 4
  • 对于100%的数据,保证1≤n≤10 6,1≤x<2 31,op∈{1,2,3}
  • 解析

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
const int N = 1000010;
int h[N], ph[N], hp[N], cnt;
void head_swap(int a, int b)
{swap(ph[hp[a]], ph[hp[b]]);swap(hp[a], hp[b]);swap(h[a], h[b]);
}
void down(int u)
{int t = u;if(u * 2 <= cnt && h[u * 2] < h[t]) t = u * 2;if(u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t]) t = u * 2 + 1;if(u != t){head_swap(u, t);down(t);}
}
void up(int u)
{while(u/2 && h[u/2] > h[u]){head_swap(u, u/2);u >>= 1;}
}
int main()
{int n, m = 0;cin >> n;while(n--){int op, x;cin >> op;if(op == 1){cin >> x;cnt++;m++;ph[m] = cnt, hp[cnt] = m;h[cnt] = x;up(cnt);}else if(op == 2){printf("%d\n", h[1]);}else{head_swap(1, cnt);cnt--;down(1);}}return 0;
}

代码与模拟堆的题是比较相似的,不同的就是只需要完成前三个基本操作,而且主函数这里是用了条件语句,满足op那里的要求的

p1334 瑞瑞的木板

题目背景

瑞瑞想要亲自修复在他的一个小牧场周围的围栏。

题目描述

他测量栅栏并发现他需要 n 根木板,每根的长度为整数 li。于是,他买了一根足够长的木板,长度为所需的 n根木板的长度的总和,他决定将这根木板切成所需的 n 根木板(瑞瑞在切割木板时不会产生木屑,不需考虑切割时损耗的长度)。

瑞瑞切割木板时使用的是一种特殊的方式,这种方式在将一根长度为 x的木板切为两根时,需要消耗 x个单位的能量。瑞瑞拥有无尽的能量,但现在提倡节约能量,所以作为榜样,他决定尽可能节约能量。显然,总共需要切割 (n−1) 次,问题是,每次应该怎么切呢?请编程计算最少需要消耗的能量总和。

输入格式

输入的第一行是整数,表示所需木板的数量 n。

第 2 到第 (n+1) 行,每行一个整数,第 (i+1)行的整数 l代表第 i 根木板的长度 lil.

输出格式

一个整数,表示最少需要消耗的能量总和。

输入样例

3
8
5
8

输出样例

34

说明/提示

输入输出样例 1 解释

将长度为 21 的木板,第一次切割为长度为 8 和长度为 13的,消耗 21 个单位的能量,第二次将长度为 13 的木板切割为长度为 5 和 8 的,消耗 13 个单位的能量,共消耗 34个单位的能量,是消耗能量最小的方案。

解析

以四块木板为例,来进行n块木板的推广

我们可以知道,割木板的次数是一定的,是N-1次,割长度为x的木板时,能量为x,先假设我们需要如图cegf四种长度的木板,那么现在问题可以转化为如何将这四种木板拼接成一块木板,所需的能量最小。那么我们就可以知道,先fg这两块长度最小的木板相加所需能量最小,将f与g相加之后,问题又可以转化为dec这三块木板拼接,怎样能量最小,同样的道理,找出三块中长度最小的两块相加,能量最小。最后我们根据这四个木板,可以得出普遍的结论了。就是每次取出堆顶的两个元素,将他们的和加入去除这两个元素的新堆中,并更新答案

#include <iostream>
#include <algorithm>using namespace std;
int n;
long long l,s[50000],da;//题目数字给的太大了,不开long long过不了。
void up(int u)//上浮,将一个新值按规矩上移(每个子节点都大于它的父亲节点)
{while(u!=1)//到顶结束{int c=u>>1;//位运算,相当于除以2(向下取);if(s[u]<s[c])swap(s[u],s[c]);else//找到自己位置也可以结束break;u=c;}
}
void down()//下沉,将一个较大值按规矩下移(顺便找到新的最小)
{int u=1;while((u<<1)<=n){int c=u<<1;//相当于乘2int t=u;//t表示我当前的值和t的值交换if(c<=n&&s[u]>s[c])t=c;//有左边并且可换if(s[u]>s[c+1]&&s[c]>s[c+1]&&c+1<=n)t=c+1;//有右边并且比左边好if(t!=u)//不等交换swap(s[u],s[t]);else//找到位置,不动了break;u=t;}
}
int main()
{cin>>n;for(int i=1;i<=n;i++)//这个循环是将木块的长度排成一个堆{cin>>l;s[i]=l;up(i);}for(int i=1;n!=1;i++)//当我节点个数为1时就做完了{int k=s[1];s[1]=s[n--];down();//删除最小值k=k+s[1];s[1]=s[n--];down();//删除新堆中的最小值s[++n]=k;up(n);//将k即两个小值之和插入堆中形成新的堆da=da+k;//最后是累计答案}cout<<da;
}

p1628合并排序

题目描述

有N个单词和字符串T,按字典序输出以字符串T为前缀的所有单词。

输入格式

输入文件第一行包含一个正整数N;

接下来N行,每行一个单词,长度不超过100;

最后一行包含字符串T。

【数据规模】

对于60%的数据,满足1≤N≤1000;

对于100%的数据,满足1≤N≤100000且所有字符均为小写字母;

输出格式

按字典序升序输出答案。

输入样例

6
na
no
ki
ki
ka
ku
k

输出样例

ka
ki
ki
ku

解析

#include <iostream>
#include <algorithm>
#include<string>
using namespace std;
int n;
string s[100001], m;
bool check(string s)
{string x; for(int i = 0; i < m.length(); i++)//m有多少个字母就将单词中的前多少位提出来{x += s[i];}if(x == m)//直接比较拼接后的字符串与m是否相等{return true;}else{return false;}
}
int main()
{cin>>n;//输入单词的个数nfor(int i = 1; i <= n; i++)//用循环输入n个单词{cin >> s[i];}cin >> m;//输入字符串msort(s + 1, s + n + 1);//STL中自带排序函数sort,sort给给定区间内所有元素进行排序,在这里直接将字母按照字典顺序排好 for(int i = 1; i <= n; i++){if(check(s[i]))//当拼接后的字母与m相等时,则输出{cout << s[i] << endl;}}return 0;
}

p1878舞蹈课

题目描述

有n个人参加一个舞蹈课。每个人的舞蹈技术由整数来决定。在舞蹈课的开始,他们从左到右站成一排。当这一排中至少有一对相邻的异性时,舞蹈技术相差最小的那一对会出列并开始跳舞。如果不止一对,那么最左边的那一对出列。一对异性出列之后,队伍中的空白按原顺序补上(即:若队伍为ABCD,那么BC出列之后队伍变为AD)。舞蹈技术相差最小即是ai的绝对值最小。

任务是模拟以上过程,确定跳舞的配对及顺序。

输入格式

第一行为正整数n(1<=n<=2*10^5):队伍中的人数。下一行包含n个字符B或者G,B代表男,G代表女。下一行为n个整数ai(ai<=10^7)。所有信息按照从左到右的顺序给出。在50%的数据中,n<=200。

输出格式

第一行:出列的总对数k。接下来输出k行,每行是两个整数。按跳舞顺序输出,两个整数代表这一对舞伴的编号(按输入顺序从左往右1至n编号)。请先输出较小的整数,再输出较大的整数。

输入输出样例

4BGBG4 2 4 3
23 41 2

分析题目后得到以下几个流程:

1.先建一个Bool数组(或者Char数组),用于存放性别

2.输入舞蹈技术值,同时将一对异性入堆(入堆的是舞蹈技术相差)

3.取出堆顶那一对人(理由:小根堆中根最小)

4.保证此时堆顶那一对人不是已经出堆的人

5.讲不上后的队伍再次取出一对异性入堆

6.重复3、4、5,直到堆为空

7.输出

代码

#include<cstdio>
const int maxn = 200010;
struct node{int value,l,r;friend bool operator > (node aa,node bb){return aa.value > bb.value || (aa.value == bb.value && aa.l > bb.l);} }heap[maxn],tmp;
void swap(node &a,node &b){tmp = a,a = b,b = tmp;}
int abs(int value){return value < 0?-value:value;}
//手写swap,abs函数
int n,a[maxn],heap_size,tot,tl[maxn],tr[maxn];
bool b[maxn],f[maxn];
void put(int value,int l,int r){int now = ++heap_size,next;heap[heap_size].value = value,heap[heap_size].l = l,heap[heap_size].r = r;while(now > 1){next = now >> 1;if(heap[now] > heap[next]) return;swap(heap[now],heap[next]);now = next;}
}
void get(){int now = 1,next;heap[1].value = heap[heap_size].value,heap[1].l = heap[heap_size].l,heap[1].r = heap[heap_size--].r;while(now << 1 <= heap_size){next = now << 1;if(next < heap_size && heap[next] > heap[next + 1]) next++;if(heap[next] > heap[now]) return;swap(heap[now],heap[next]);now = next;}
}int main(){scanf("%d\n",&n);for(int i = 0;i < n;i++){char ch = getchar();f[i] = ch == 'B';//若这个人他是'B'置f[i]为true,反之亦反 }//巧妙地输入情况 for(int i = 0;i < n;i++){scanf("%d",&a[i]);//输入舞蹈技术 int j = i - 1;//置j为i前面那个人 if(i && f[i] ^ f[j]) put(abs(a[i] - a[j]),j,i);//如果i不是指向第一个人,且f[i] != f[j],将舞蹈技术值差和两个人的下标入堆 }while(heap_size){int l = heap[1].l,r = heap[1].r,ll,rr;//当前最小的那一对出堆 b[l] = b[r] = true; tl[++tot] = l + 1,tr[tot] = r + 1;do{get();if(!heap_size) break; ll = heap[1].l,rr = heap[1].r;}while(b[ll] || b[rr]);//此操作维护该堆直至堆顶不为已出堆的元素 while(l >= 0 && b[l]) l--;while(r < n && b[r]) r++; //寻找空白两边的元素 if(l >= 0 && r < n && f[l] ^ f[r]) put(abs(a[l] - a[r]),l,r);//将其入堆 }printf("%d",tot);for(int i = 1;i <= tot;i++) printf("\n%d %d",tl[i],tr[i]); //输出答案 return 0;
}

堆——以洛谷p3378,p1334,p1628,p1878为例相关推荐

  1. 洛谷 P3378 【模板】堆

    2019-05-30 题目 : 洛谷 P3378 [模板]堆 : https://www.luogu.org/problemnew/show/P3378 题目描述 如题,初始小根堆为空,我们需要支持以 ...

  2. 升序堆和降序堆(优先队列) 洛谷1801

    1 // 洛谷1801 2 // 一个升序堆,一个降序堆 3 // 降序堆维护序列的前i个最小值 4 // 插如元素的时候,如果x小于降序堆最大值,则替换,并将最大值插入升序堆:否则,直接插入升序堆 ...

  3. 洛谷 P3378 【模板】堆

    嗯... 这是一道堆的模板题,但我个人感觉最好的做法就是通过优先队列来进行操作... 首先我们看一下这道水题.... 题目描述 如题,初始小根堆为空,我们需要支持以下3种操作: 操作1: 1 x 表示 ...

  4. 洛谷P3378 【模板】堆

    题目描述 如题,初始小根堆为空,我们需要支持以下3种操作: 操作1: 1 x 表示将x插入到堆中 操作2: 2 输出该小根堆内的最小数 操作3: 3 删除该小根堆内的最小数 输入输出格式 输入格式: ...

  5. 洛谷:P5707 【深基2.例12】上学迟到

    首先我想说一些坑爹的地方: 1.标准化格式:在前面添0: printf("%02d:%02d",count,sum); 2.由于单位是分钟,有时候s/v是小数,所以要加一.而如果是 ...

  6. 【洛谷】P5707 【深基2.例12】上学迟到

    原题链接 P5707 [深基2.例12]上学迟到 ac代码 #include <iostream> #include <cstdio> using namespace std; ...

  7. 洛谷or牛客数据结构+算法

    栈思想:先进后出 tips:栈里能放下标就放下标 (牛客)小c的计事本(直接用stack可以简化代码,且不会被自己绕晕,当时没意识到) (牛客)吐泡泡(没意识到用栈),(牛客)好串 1.后缀表达式(栈 ...

  8. 洛谷P4911 河童重工的计算机

    传送门 题目背景 河童重工业会社的计算机产品在幻想乡中有着极其广泛的应用. 有一天,妖怪之山发大水啦!洪水夹杂着泥沙和滚木汹涌着冲进了河童的城市. 本来河童们的机械设施都是防水的,可是洪水还是对城市造 ...

  9. python输出一个简单的田字格、用函数简化其代码_Solution Method: 洛谷 P1001 A+B Problem(Python 3 基本输入输出方法及代码简化)...

    本文从 洛谷 P1001 A+B Problem 为例,讲一讲 Python 3 在算法竞赛中的一些基本输入输出方法,以及一些利用 Python 3 特性的代码简化 以下为本文将涉及的内容: inpu ...

最新文章

  1. 【052】测试数据引发的骚乱
  2. 布隆过滤器、一致性哈希算法总结
  3. linux内核时间second,闰秒(leap second)和linux/unix时间
  4. mysql当前时间加一天_MySQL 的加锁处理,你都了解的一清二楚了吗?
  5. 音视频技术开发周刊(第126期)
  6. POJ 1222 1681 1830 3185 开关灯问题 (高斯消元 异或方程组)
  7. leetcode 959. 由斜杠划分区域(并查集)
  8. go linux 源码编译环境,修改并编译golang源码
  9. ssh解决root_unlock_time问题
  10. xcodebuild构建时报错unknown error -1=ffffffffffffffff Command /bin/sh failed with exit code 1
  11. 申请企业邮箱有什么流程?
  12. 基于树莓派的专用摄像头实时监控
  13. js Date 日期函数
  14. 吊打Navicat?这款神器牛逼了~~ [ 必看 ]
  15. 解决 Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8
  16. 大屏一体机!奥可视新品A5亮点浅析
  17. IMDB评出来的100部最难看的电影排行榜
  18. 2016杭州云栖大会随笔
  19. 剁手节致敬!听当年的老人讲述阿帕网(互联网前身)诞生的故事
  20. The application server could not be contacted

热门文章

  1. 传说之下打开debug模式超超超超超超超超详细方法
  2. 第三章 区块链进阶 [18]
  3. 自学测试入门—用户注册功能的测试
  4. 最详细的Android Bitmap回收机制(从2.3到7.0,8.0)
  5. PMP 考点 第三章 项目经理的角色
  6. Latex---局部调大字体--下划线--首行缩进--悬挂缩进
  7. 小程序拼团营销怎么做
  8. matlab程序运行不停,MATLAB一直运行是为什么?
  9. python 爬虫 requests 错误汇总
  10. iOS Safari阅读模式分析过程