【BZOJ4345】[POI2016]Korale 堆(模拟搜索)
【BZOJ4345】[POI2016]Korale
Description
Input
Output
Sample Input
3 7 4 3
Sample Output
1 3 4
题解:求第k小我们自然想到超级钢琴那题,而枚举所有集合要用搜索,所以我们要模拟搜索的过程。
起初,我们将一个空集扔到小根堆中,然后每次取出堆顶元素,考虑DFS时,我们是从左到右枚举每个数,可能选也可能不选,那么我们模拟这个过程,分两种情况:
1.加入一个数,那么显然是加入右面最小的数。
2.将最后一个数换成一个数,那么显然是将当前数换成刚好比当前数大的那个数,这里采用超级钢琴的做法,维护当前数的选择区间[l,r],假设当前数是x,那么在[l,x)和(x,r]中寻找新的最小数,替换当前数。
但是如何保证字典序最小呢?首先首位必须最小,那么我们将DFS的顺序反过来即可;然后记录一下每个状态是由哪个状态得到的,在取出一个状态的时候顺便记录一个这个状态的排名,比较时比较上一个状态的排名即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn=1000010;
typedef long long ll;
int n,m,N;
ll v[maxn];
int mx[21][maxn],Log[maxn];
struct node
{
ll sum;
int x,pre,l,r,rank;
}p[maxn*3];
struct number
{
int a;
number() {}
number(int x) {a=x;}
bool operator < (const number &c) const
{
int b=c.a;
if(p[a].sum!=p[b].sum) return p[a].sum>p[b].sum;
if(p[a].x!=p[b].x) return p[a].x>p[b].x;
return p[p[a].pre].rank>p[p[b].pre].rank;
}
};
priority_queue<number> q;
inline int MX(int a,int b)
{
return ((v[a]==v[b])?(a<b):(v[a]<v[b]))?a:b;
}
inline int query(int a,int b)
{
register int c=Log[b-a+1];
return MX(mx[c][a],mx[c][b-(1<<c)+1]);
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
void print(int x)
{
if(!x) return ;
printf("%d ",p[x].x),print(p[x].pre);
}
int main()
{
n=rd(),m=rd()-1;
if(!m)
{
printf("0\n");
return 0;
}
register int i,j,a,b,cnt;
ll last=-1;
for(i=1;i<=n;i++) v[i]=rd(),mx[0][i]=i;
for(i=2;i<=n;i++) Log[i]=Log[i>>1]+1;
for(j=1;(1<<j)<=n;j++) for(i=1;i+(1<<j)-1<=n;i++) mx[j][i]=MX(mx[j-1][i],mx[j-1][i+(1<<(j-1))]);
N=1,p[1].x=query(1,n),p[1].sum=v[p[1].x],p[1].pre=0,p[1].l=1,p[1].r=n;
q.push(number(1));
while(m--)
{
i=q.top().a,q.pop();
if(!m)
{
printf("%lld\n",p[i].sum),print(i);
return 0;
}
if(p[i].sum>last) last=p[i].sum,cnt=1;
else cnt++;
p[i].rank=cnt;
if(p[i].x!=1)
{
j=++N,p[j].pre=i,p[j].l=1,p[j].r=p[i].x-1,p[j].x=query(1,p[i].x-1),p[j].sum=p[i].sum+v[p[j].x];
q.push(number(j));
}
a=(p[i].x>p[i].l)?query(p[i].l,p[i].x-1):0;
b=(p[i].x<p[i].r)?query(p[i].x+1,p[i].r):0;
if(a)
{
j=++N,p[j].pre=p[i].pre,p[j].x=a,p[j].l=p[i].l,p[j].r=p[i].x-1,p[j].sum=p[p[i].pre].sum+v[a];
q.push(number(j));
}
if(b)
{
j=++N,p[j].pre=p[i].pre,p[j].x=b,p[j].l=p[i].x+1,p[j].r=p[i].r,p[j].sum=p[p[i].pre].sum+v[b];
q.push(number(j));
}
}
}
【BZOJ4345】[POI2016]Korale 堆(模拟搜索)的更多相关文章
- [bzoj4345][POI2016]Korale_堆_贪心_线段树_dfs
bzoj4345 POI2016 Korale 题目链接:https://lydsy.com/JudgeOnline/problem.php?id=4345 数据范围:略. 题解: 由于$k$的范围问 ...
- BZOJ4345 : [POI2016]Korale
只考虑第一问,将珠子按照价值从小到大排序,设排序后第$i$小的为$b[i]$,定义二元组$(x,y)$表示当前珠子的总价值为$x$,用的价值最大的珠子为$y$,用一个小根堆来维护所有状态.一开始往堆中 ...
- 【LOJ6254】最优卡组 堆(模拟搜索)
[LOJ6254]最优卡组 题面 题解:常用的用堆模拟搜索套路(当然也可以二分).先将每个卡包里的卡从大到小排序,然后将所有卡包按(最大值-次大值)从小到大排序,并提前处理掉只有一张卡的卡包. 我们将 ...
- 【BZOJ4524】[Cqoi2016]伪光滑数 堆(模拟搜索)
[BZOJ4524][Cqoi2016]伪光滑数 Description 若一个大于1的整数M的质因数分解有k项,其最大的质因子为Ak,并且满足Ak^K<=N,Ak<128,我们就称整数M ...
- JavaScript在表格中模拟搜索多关键词搜索和筛选
模拟搜索需要实现以下功能: 1.用户的模糊搜索不区分大小写,需要小写字母匹配同样可以匹配到该字母的大写单词. 2.多关键词模糊搜索,假设用户关键词以空格分隔,在关键词不完整的情况下仍然可以匹配到包含该 ...
- Codeforces Good Bye 2016 D 模拟搜索?
给出烟花的爆炸方式和爆炸次数 问最后有多少个格子会被炸到 如果dfs的话会超时... 利用模拟每一层来搜索..? 思想就是一开始有一个爆炸点向上 然后模拟完第一段 会产生一个爆炸点 朝两个方向 就用v ...
- HDU 3262 Seat taking up is tough (模拟搜索)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3262 题意:教室有n*m个座位,每个座位有一个舒适值,有K个学生在不同时间段进来,要占t个座位,必须是连 ...
- bzoj 4345: [POI2016]Korale
Description 有n个带标号的珠子,第i个珠子的价值为a[i].现在你可以选择若干个珠子组成项链(也可以一个都不选),项链的价值为所有珠子的价值和.现在给所有可能的项链排序,先按权值从小到大排 ...
- BZOJ4977[Lydsy1708月赛]跳伞求生——贪心+堆+模拟费用流
题目链接: 跳伞求生 可以将题目转化成数轴上有$n$个人和$m$个房子,坐标分别为$a_{i}$和$b_{i}$,每个人可以进一个他左边的房子,每个房子只能进一个人.每个房子有一个收益$c_{i}$, ...
随机推荐
- Linux 添加开机启动项的三种方法
linux 添加开机启动项的三种方法. (1)编辑文件 /etc/rc.local 输入命令:vim /etc/rc.local 将出现类似如下的文本片段: #!/bin/sh## This scri ...
- ContentObserver与DatasetObserver区别
1. ContentObserver ContentObserver主要是通过Uri来监测特定的Databases的表,如果该Databases表有变动则会通知更新cursor中的数据. 如果 ...
- github 搜索技巧
1.关键词 + 指定开发语言 bitcoin language:javascript 2.关键词 + stars 数量 + forks 数量 bitcoin stars:> forks:>
- zookeeper(一):功能和原理
简介 ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现.分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅.负载均衡.命名服务.分 ...
- 关于Tomcat 开启不了的几点解释
这段时间基本熟悉java语言基本语法包,类(内部,外部),整体结构跟c#还是有点差异,在接口,多态,抽象等几乎一致,唯一差异仅存在于关键字上. 在用了几天记事本熟悉代码上,昨天晚上就准备转想myEcl ...
- jquery实现页面的搜索功能
$(function(){ $("input[type=button]").click(function(){ var txt=$("input[type=text]&q ...
- jsp中判断对象是否存在
<!-- 如果user对象存在,则显示用户名,如果不存在,则显示空值--> <input type="text" id="userName" ...
- C#高级学习群欢迎你(群号 128874886)
C#高级学习群,有着C# ,Asp.net ,Wpf等技术经验相当丰富的工程师,秉承着刘群主开源共享的精神,为新手和高手们提供了良好的学习交流平台,自创群以来,为群员解决了不少的技术难题,大大提高了学 ...
- GraphicsMagick +im4java高并发处理大型网站图片工具-图片剪切、遮蔽、水印添加之环境搭建
环境: centos 6.5 GraphicsMagick 下载安装 准备环镜: 需要依赖zlib图片操作函数库 下载地址:http://www.zlib.net/ 编译安装 .tar.gz cd z ...
- Centos6.X 安装MongoDb
1.查看linux版本,之所以查看linux版本,是因为centos7和以前版本用的防火墙不一样,安装完mongodb后,需要关闭防火墙(或者其他方法,专业运维人员使用,我们这里为简单,直接关闭即可) ...