洛谷 P1878 舞蹈课 —— 小顶堆
This way
题意:
有 n个人参加一个舞蹈课。每个人的舞蹈技术由整数来决定。在舞蹈课的开始,他们从左到右站成一排。当这一排中至少有一对相邻的异性时,舞蹈技术相差最小的那一对会出列并开始跳舞。如果不止一对,那么最左边的那一对出列。一对异性出列之后,队伍中的空白按原顺序补上(即:若队伍为 ABCD,那么 BC 出列之后队伍变为 AD)。舞蹈技术相差最小即是 ai的绝对值最小。
任务是模拟以上过程,确定跳舞的配对及顺序。
题解:
小顶堆的解法:
同样直接维护小顶堆,堆中值就是相邻两个异性的值之差。
那么首先建堆很容易,直接按照插入一个数的做法将相邻为异性的差塞到堆中,进行up操作即可。就算是GBGBGB这种也无所谓,我们只需要在后面判断某个人是否已经配对了即可。
那么现在只需要考虑删除以及后续的操作即可。这个时候上述情况就需要去考虑了,那么我们将已经取出来的人打个标记:lef[x]表示下标≤x的最后一个未被配对的人,rig[x]表示下标≥x的最早一个未被配对的人,这样我们就能在删掉L,R两个下标的人之后,快速地去找到下两个能匹配的人。
我在这里使用了路径压缩,也就是findl,findr,以防极端情况TLE。
这样删除h[1]节点之后,就将旁边的人加入进来,但是要注意到了边界(0和n+1)的情况。
同时,要注意由于之前塞到堆里面的人有可能被占用掉了,所以要判一下h[1]是否有人被占用即可,如果有就当做删除处理。
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
const int N=2e5+5;
int siz;//小顶堆
struct heap{int val,l,r;bool operator< (const heap&a)const {if(val==a.val)return l<a.l;return val<a.val;}
}h[N];
void up(int pos){while(pos!=1 && h[pos]<h[pos>>1])swap(h[pos],h[pos>>1]),pos>>=1;
}
void down(int pos){while((pos<<1)<=siz){int ch=pos<<1;if(ch+1<=siz && h[ch+1]<h[ch])ch+=1;if(h[ch]<h[pos])swap(h[ch],h[pos]);else break;pos=ch;}
}
int lef[N],rig[N],a[N];
int findl(int x){return x==lef[x]?x:lef[x]=findl(lef[x]);}
int findr(int x){return x==rig[x]?x:rig[x]=findr(rig[x]);}
char s[N];
vector<pii>ans;
int main()
{int n;scanf("%d",&n);for(int i=1;i<=n+1;i++)lef[i]=rig[i]=i;scanf("%s",s+1);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=2;i<=n;i++)if(s[i]!=s[i-1])h[++siz]={abs(a[i]-a[i-1]),i-1,i},up(siz);while(siz){int l=h[1].l,r=h[1].r;while(siz && (l!=lef[l] || r!=lef[r])){swap(h[1],h[siz--]);down(1);l=h[1].l,r=h[1].r;}if(!siz)break;ans.push_back({l,r});lef[l]=lef[r]=findl(l-1),rig[r]=rig[l]=findr(r+1);if(lef[l]!=0&&rig[r]!=n+1&&s[lef[l]]!=s[rig[r]])h[++siz]={abs(a[lef[l]]-a[rig[r]]),lef[l],rig[r]};}printf("%d\n",ans.size());for(pii i:ans)printf("%d %d\n",i.first,i.second);return 0;
}
洛谷 P1878 舞蹈课 —— 小顶堆相关推荐
- 优先级队列(小顶堆)的dijkstra算法
php实现迪杰斯特拉算法,并由小顶堆优化 1 <?php 2 3 class DEdge 4 { 5 public $nextIndex, $length; 6 7 public functio ...
- CodeForces - 867E Buy Low Sell High (贪心 +小顶堆)
https://vjudge.net/problem/CodeForces-867E 题意 一个物品在n天内有n种价格,每天仅能进行买入或卖出或不作为一种操作,可以同时拥有多种物品,问交易后的最大利益 ...
- 堆排序之 大顶堆和小顶堆 c语言
百度得到的堆定义如下: 堆的定义如下:n个元素的序列{k1,k2,ki,-,kn}当且仅当满足下关系时,称之为堆. (ki <= k2i,ki <= k2i+1)或者(ki >= k ...
- priority_queue实现大顶堆和小顶堆
升序队列,小顶堆 priority_queue <int,vector<int>,greater<int> > q; 降序队列,大顶堆 priority_queue ...
- 【LeetCode笔记】347. 前K个高频元素(Java、优先队列、小顶堆、HashMap)
文章目录 题目描述 思路 & 代码 更新版:引入 stream 流 + Lambda 题目描述 时间复杂度小于O(n*logn),否则直接sort,再遍历就很轻松. 很有学习价值的题目,第一次 ...
- 优先队列默认是小顶堆吗_一分钟带你读懂什么是堆?
堆其实就是一种特殊的队列--优先队列. 普通的队列游戏规则很简单:就是先进先出:但这种优先队列搞特殊,不是按照进队列的时间顺序,而是按照每个元素的优先级来比拼,优先级高的在堆顶. 这也很容易理解吧,比 ...
- 小顶堆数据结构C/C++代码实现
相比队列和栈,很多人可能对堆的概念比较陌生,下面个给出堆的本质概念 一.堆也是一种数据结构,从实际应用意义来说,他是一种最优级别数据永远在第一位的队列,本文皆以最小值为例(小顶堆),即它变相是一种会永 ...
- 剑指offer:数据流中的中位数(小顶堆+大顶堆)
1. 题目描述 /**如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的 ...
- 剑指Offer之寻找数据流中的中位数【包含大顶堆小顶堆解释】
数据流中的中位数 题目描述 题解 最小堆和最大堆解释 参考链接 题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶 ...
最新文章
- 客快物流大数据项目(七):Docker总结
- 重磅直播|中科慧眼崔峰博士详解深度相机原理及其应用
- MySQL安装、基本账户安全(5.0以后版本)
- java基础---设计一个死锁
- Java04-day04【IDEA(概述、启动配置、项目结构、内容辅助键、快捷键、模块操作)、数组(定义详解、动态初始化、访问)、内存分配、数组内存图】
- 大厂面试算法系列-如何从无序链表中移除重复项(一)-顺序删除
- VS2017编写C++多文件时,出现LNK2005、LNK1169报错的解决方法
- 那些让程序员炸毛的奇葩需求,说起来满满的都是泪!
- BD 之 逻辑题 赛马
- cmos逻辑门传输延迟时间_Verilog设计与逻辑综合实例解析(低功耗)
- 安卓玩机搞机技巧综合资源-----闲置手机当摄像头 当监控 上网课必备 多软件评测【十四】
- 高次同余式的解数和解法
- 美术课程对计算机的好处,学美术的十大好处
- matlab人脸识别样本库建立,facenet 人脸识别(二)——创建人脸库搭建人脸识别系统...
- Win获取本地SVN帐号密码
- API 编排的应用及痛点
- PPTV免费会员赠送活动
- 上海数字化品牌营销 whale 帷幄数字化品牌营销案例
- element 多层导航菜单,让网页设计更简洁、美观
- 浅析企业ERP系统运维体系的建立
热门文章
- 微信小程序免费资源大全
- 小米笔记本第一排按键功能失灵 [ 解决办法 ]
- billu_b0x靶场通关
- 大疆Tello EDU版本(新发布)
- 全球及中国常规救生艇行业研究及十四五规划分析报告
- qcqa是什么职位_qc经理是什么职位
- 守护线程daemon
- Gradual warmup lr schedule--pytorch
- iOS审核总被拒?腾讯教你提升iOS审核通过率!
- 群辉nas虚拟linux,UNRAID教程:3分钟 用unraid自带的虚拟机 安装 黑群晖NAS DSM系统 很强大!...