题目传送门

贪心:

一个人 \(i\) 要投票,两种情况:花钱,或当前的人数达到了 \(m_i\)。

而当前达到 \(m_i\) 的话所有 \(m_j \le m_i\) 也就达到要求了。

所以考虑将所有人按 \(m\) 从小到大排序。用 \(vetcor\) 当桶。

其次考虑如何贿赂最优。当前如果要达到 \(m_i\),优先考虑贿赂 \(m\) 更大的。因为贿赂比他小的可以达到的还是 \(m_i\),贿赂比他大的就可以达到 \(m_i+1\)。同时,后面的要求比前面高,不用再考虑,会更优。

而在比 \(m_i\) 大的所有人中,贪心贿赂 \(p_i\) 更小的显然更好。所以,需要维护比 \(m_i\) 大的所有人中 \(p_i\) 的最小值。考虑用小根堆维护。

堆:

没怎么用过,补

用 \(stl\) 中的优先队列。

小根堆:

priority_queue< 数据类型 ,vector< 数据类型 >,greater< 数据类型 > > q;

大根堆:

priority_queue< 数据类型 > q;

priority_queue< 数据类型 ,vector< 数据类型 >,less< 数据类型 > > q;

基本操作:

empty()  //判断一个队列是否为空
pop() //删除队顶元素
push(x) //加入一个元素 x
size() //返回优先队列中拥有的元素个数
top() //返回优先队列的队顶元素

其存取时间复杂度 \(O(logn)\)

板:

P3378

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,op;
ll x;
priority_queue<ll,vector<ll>,greater<ll> > q;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&op);
if(op==1){
scanf("%lld",&x);
q.push(x);
}
else if(op==2) printf("%lld\n",q.top());
else q.pop();
}
return 0;
}

P1334 瑞瑞的木板

将分割看成合成。每次选取两块长度最小的合答案最小。

用小根堆维护当前最小两块板,合完删掉这两块,并加入他们的和。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,a,_1,_2;
ll ans;
priority_queue<int,vector<int>,greater<int> > q;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a);
q.push(a);
}
for(int i=1;i<n;i++){
_1=q.top(),q.pop();
_2=q.top(),q.pop();
q.push(_1+_2);
ans+=(ll)_1+(ll)_2;
}
printf("%lld",ans);
return 0;
}

双倍经验:合并果子

对顶堆:

对顶堆用于维护第 \(k\) 大的数。

是堆顶相对的一个大根堆和一个小根堆,其中小根堆存较大的一部分数,大根堆存较小的一部分数。大根堆堆顶一般是第 \(k\) 大数。插入:根据需要插到插到大根堆或小根堆,然后调整堆顶。

P1801 黑匣子

用对顶对维护第 \(i\) 大的数。插入到大根堆,若还不到 \(get\) 就把大根堆堆顶调到小根堆。每次 \(get\) 后调整一位堆顶,达到 \(i++\) 的效果。

#include<bits/stdc++.h>
using namespace std;
int n,m,a[200005],u[200005],now;
priority_queue<int> b;
priority_queue<int,vector<int>,greater<int> > s;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&u[i]);
for(int i=1;i<=m;i++){
while(now<u[i]){
b.push(a[++now]);
s.push(b.top());
b.pop();
}
printf("%d\n",s.top());
b.push(s.top());
s.pop();
}
return 0;
}

P1168 中位数

若当前数 \(>mid\),则放到小根堆,否则放到大根堆。

每次奇数个都要查询并更新 \(mid\),所以两个堆的大小差不超过 \(2\)。所以每次奇数个时,判断。若小根堆更大就更新 \(mid\) 为小根堆堆顶,并向大根堆调整。若大根堆更大,就更新 \(mid\) 为大根堆堆顶,并向小根堆调整。若大小相等, \(mid\) 不变。

#include<bits/stdc++.h>
using namespace std;
int n,a,mid;
priority_queue<int> b;
priority_queue<int,vector<int>,greater<int> > s;
int main(){
scanf("%d%d",&n,&a);
printf("%d\n",a);
mid=a;
for(int i=2;i<=n;i++){
scanf("%d",&a);
if(a>mid) s.push(a);
else b.push(a);
if(i%2==0) continue;
if(b.size()>s.size()){
s.push(mid);
mid=b.top();
b.pop();
}
else if(b.size()<s.size()){
b.push(mid);
mid=s.top();
s.pop();
}
printf("%d\n",mid);
}
return 0;
}

重载运算符

用于结构体中的比较。

P1878 舞蹈课

删除后补位,用链表实现。

同时,优先取插值较小的一对,可以用小根堆维护每一对的差值。同时要记录两人的编号,要用结构体。

首先把初始的相邻男女插到堆中,之后每次取堆顶记录答案,取完后标记掉,并更新左右编号(链表)。若出现的新的可行的一对,就再入队,直到队列为空。

重载运算符中,第一关键字为差值,第二关键字为左边人的编号。

#include<bits/stdc++.h>
using namespace std;
int n,a[200005],cnt=0,ans[2][200005];
int l[200005],r[200005],x,y;
bool fl=1,mark[200005];
struct node{
int w,c,d;
};
bool operator<(node a,node b){
if(a.w!=b.w) return a.w>b.w;
else return a.c>b.c;
}
priority_queue<node> q;
string s;
int main(){
scanf("%d",&n);
cin>>s;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++){
if(s[i-1]!=s[i]){
node k;
k.w=abs(a[i]-a[i+1]),k.c=i,k.d=i+1;
q.push(k);
}
}
for(int i=1;i<=n;i++) l[i]=i+1,r[i]=i-1;
while(q.size()){
node t=q.top();
q.pop();
x=t.c,y=t.d;
if(mark[x]!=0||mark[y]!=0) continue;
l[r[x]]=l[y];
r[l[y]]=r[x];
ans[0][++cnt]=x,ans[1][cnt]=y;
mark[x]=mark[y]=1;
if(mark[r[x]]==0&&mark[l[y]]==0){
if((s[r[x]-1]+s[l[y]-1])==('G'+'B')){
node k;
k.w=abs(a[r[x]]-a[l[y]]),k.c=r[x],k.d=l[y];
q.push(k);
}
}
}
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++) printf("%d %d\n",ans[0][i],ans[1][i]);
return 0;
}

P1631 序列合并

因为两数列按顺序给出,所以可以得到:

不管怎么样,\(A\) 序列中的第一个数绝对要选,那么这个数可能和 \(B\) 序列中的任何一个数组成的数对被选,全部加入优先队列中,这样处理了 \(i,j+1\) 的情况。

还有 \(i+1,j\) 的情况,每次输出一个和之后,将 \(B\) 序列中的第 \(i\) 个数对应的 \(A\) 序列中的第 \(j\) 个数的 \(j++\),组成数对。

但是这样数对还是容易重复。可以用一个数组记录一下,\(id[i]\) 表示 \(B\) 序列中的第 \(i\) 个数与 \(A\) 序列中的第几个数相加,每次入队的时候累加 \(id\) 数组就不会造成重复了。

用结构体存和与序号。但 priority_queue<node> 是大根堆,而本题需要小根堆。所以重载运算符:

bool operator<(node a,node b){
return a.v>b.v;
}

将小于强制定义为大于即可。

#include<bits/stdc++.h>
using namespace std;
struct node{
int v,c;
};
bool operator<(node a,node b){
return a.v>b.v;
}
priority_queue<node> q;
node k;
int a[100005],b[100005],id[100005],n;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
id[i]=1;
k.v=a[1]+b[i],k.c=i;
q.push(k);
}
for(int i=1;i<=n;i++){
printf("%d ",q.top().v);
int tmp=q.top().c;
q.pop();
k.v=a[++id[tmp]]+b[tmp],k.c=tmp;
q.push(k);
}
return 0;
}

解决:

首先按 \(m\) 的大小,分别放在 \(vector\) 中。

然后 \(i\) 从 \(n-1\) 开始(从大到小),每次先把 \(m\) 值为 \(i\) 的人的贿赂花费放到小根堆中,然后比较堆的大小和 \(n-i\)。若 \(q.size()>n-i\) ,则说明人数不够,就挑堆顶贿赂,直到够了为止。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll T,n,p,m,ans;
vector<ll> a[200005];
priority_queue<ll,vector<ll>,greater<ll> > q;
void cl(){
ans=0;
for(int i=0;i<=n;i++) a[i].clear();
while(q.size()) q.pop();
}
void solve(){
scanf("%lld",&n);
cl();
for(int i=1;i<=n;i++){
scanf("%lld%lld",&m,&p);
a[m].push_back(p);
}
for(int i=n-1;i>=0;i--){
for(int j=0;j<a[i].size();j++){
q.push(a[i][j]);
}
while(q.size()>n-i){
ans+=q.top();
q.pop();
}
}
printf("%lld\n",ans);
return ;
}
int main(){
scanf("%lld",&T);
while(T--) solve();
return 0;
}

【笔记】CF1251E Voting 及相关的更多相关文章

  1. amazeui学习笔记--css(布局相关1)--网格Grid

    amazeui学习笔记--css(布局相关1)--网格Grid 一.总结 基本使用 1.div+class布局:amaze里面采取的就是div+class的布局方式  <div class=&q ...

  2. amazeui学习笔记--css(布局相关3)--辅助类Utility

    amazeui学习笔记--css(布局相关3)--辅助类Utility 一.总结 1.元素清除浮动: 添加 am-cf 这个 class 即可 2.水平滚动: .am-scrollable-horiz ...

  3. amazeui学习笔记--css(布局相关2)--等分网格 AVG Grid

    amazeui学习笔记--css(布局相关2)--等分网格 AVG Grid 一.总结 1.与grid区别:网格中:am-g + am-u-xx-n 等分网格中只有一个: am-avg-sm-4(在u ...

  4. 11G RAC 中 OCR 及Voting Disk 相关操作

    一.启动oracle clusterware先决条件:Oracle High Availability Services daemon(OHASD)运行在所有集群节点上1.启动整个Oracle Clu ...

  5. shell 脚本实战笔记(7)--集群网络相关知识和环境搭建

    前言: 对网络相关的知识, 做下笔记. 包括IP地址A/B/C的分类, 静态地址的配置/DNS配置, 以及网卡相关信息查看. *) A/B/C/D类网络地址的划分 IP地址=网络地址+主机地址 或 I ...

  6. ElasticSearch学习笔记-02集群相关操作_cat参数

    _cat参数允许你查看集群的一些相关信息,如集群是否健康,有哪些节点,以及索引的情况等的. 检测集群是否健康 curl localhost:9200/_cat/health?v 说明: curl 是一 ...

  7. [开发笔记]-Windows Service服务相关注意事项

    注意一:报错:“本地计算机上的 *** 服务启动后停止.某些服务在未由其他服务或程序使用时将自动停止.” 该问题主要的原因是 Service服务程序中有错误. 遇到这个问题时,无论是重新安装服务,还是 ...

  8. CentOS学习笔记--基本命令--目录的相关操作

    Linux基本命令--目录的相关操作 常见的处理目录的命令吧: cd:变换目录 pwd:显示目前的目录 mkdir:创建一个新的目录 rmdir:删除一个空的目录 cd (变换目录) cd是Chang ...

  9. LoRaWAN_stack移植笔记(一)--RF硬件相关

    和硬件相关的问题 TCXO 的使用 根据SX1276数据手册, 如果使用TCXO,则需要配置RegTcxo寄存器为0x19,代码如下 ``` c void SX1276SetTcxoConfig(vo ...

随机推荐

  1. 【java】IDEA-jar包导出与导入

    导出步骤: 1.CTRL + SHIFT + ALT + S 2.选择:Artifacts ,点击"+",在添加页面中选择:JAR-From modules with depend ...

  2. C#通过反射实现简单的控制反转和依赖注入(一)

    Java项目中通过@Autowire便可以实现将对象实例化到指定的字段,无需手动new一个对象出来,用起来非常方便,因为Java类加载器在在加载过程会将扫描所有@Servie.@Mapper.@Com ...

  3. KingbaseES V8R6备份恢复案例之---手工清理冗余历史备份

    案例说明: 对于KingbaseES V8R6的通过sys_rman执行的物理历史备份,可以在执行备份时,备份的保留(retention)策略自动清理.不能通过手工删除备份,可以通过expire参数手 ...

  4. KingbaseES V8R6集群维护案例之--修改securecmdd工具服务端口

    案例说明: 在一些生产环境,为了系统安全,不支持ssh互信,或限制root用户使用ssh登录,KingbaseES V8R6可以使用securecmdd工具支持主机之间的通讯.securecmdd工具 ...

  5. KingbaseESV8R6 垃圾回收原理以及如何预防膨胀

    背景 KingbaseESV8R6支持snapshot too old 那么实际工作中,经常看到表又膨胀了,那么我们讨论一下导致对象膨胀的常见原因有哪些呢? 未开启autovacuum 对于未开启au ...

  6. CMU 15-445 Project 0 实现字典树

    原文链接:https://juejin.cn/post/7139572163371073543 项目准备 代码.手册 本文对应 2022 年的课程,Project 0 已经更新为实现字典树了.C++1 ...

  7. 一步步搞懂MySQL元数据锁(MDL)

    某日,路上收到用户咨询,为了清除空间,想删除某200多G大表数据,且已经确认此表不再有业务访问,于是执行了一条命令'delete from bigtable',但好长时间也没删完,经过咨询后,获知dr ...

  8. vscode调试thinkhphp

    第一步先安装xdebug扩展,我用宝塔环境,所以一键安装 第二步.在vscode中安装插件 我的php.ini是这样的 xdebug.remote_enable = 1 xdebug.remote_a ...

  9. Java基础(标识符,数据类型,数据转换,变量)

    注释 Java中的注释有3种: 单行注释 // 多行注释 /**/ 文档注释 /***/ 注释不会被执行,是给我们写代码的人看的 书写注释是一个非常好的习惯 标识符 Java所有的组成部分都需要名字, ...

  10. Elastic:为Elastic Docker部署设置安全

    文章转载自:https://elasticstack.blog.csdn.net/article/details/105710973 创建docker-compose.yml 在之前的教程中,那里使用 ...