Description

 

Input

第 一行为两个空格隔开的正整数n, m,表示旅行的城市数与旅行所花的月数。接下来n行,其中第 i行包含两个空格隔开的整数Ai和Bi,Ai表示他第i个去的城市编号。Bi为0或1;如果 Bi=0则表示城市Ai没有小L想去的景点,如果Bi=1则表示城市Ai有小L想去的景点,
Ai两两不同且有1<=Ai<=N,即{Ai}为1,2....N的一个排列。
例如{2,1,3,4...N}
N<=500000,M<=200000

Output

t仅包括一行,包含m个空格隔开的正整数X1,X2...Xm,t仅包括一行,包含m个空格隔开的正整数X1,X2...Xm,为给小L安排的旅行计划对应的路线。为给小L安排的旅行计划对应的路线。

Sample Input

8 3
2 0
3 1
4 1
1 0
5 0
6 1
7 1
8 0

Sample Output

1 6 8

HINT

第1个月得到2点快乐值与2点疲劳值,第2个月得到1点快乐值与1点疲劳值,第3 个月得到1点快乐值与1点疲劳值。3个月中疲劳值与快乐值差的最大值为0,达到所有方案最小值。

可行方案有:

1  6 8

3  6 8

3  1 8

其中1 6 8字典序最小。

题解:

数组b[i]表示城市a[i]是否为有小L想去的景点,1表示有,-1表示没有

记sum[i]=b[i+1]+b[i+2]+...+b[n],S=sum[0],最大值最小为d,则

if S==0

  if sum[i]==0 的个数 >= m 则将这些等于0的数做一遍单调队列

  else d=1

else d=ceil(abs(S)/m)

证明见http://cxjyxx.me/?p=329

然后就是如何求字典序最小

我们每次要找到一个 能使后面的数仍然有解的 最小的一个数作为结尾

设这个新区间是第i个区间,结束点为k

首先这个新区间要合法,则abs(S-sum[k])/(m-i)<=d

然后要保证后面要有解,则ceil(abs(sum[k])/(m-i))<=d

然后用单调队列维护每种sum值的最小值

具体见代码

code:

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 500005
#define base maxn
using namespace std;
char ch;
bool ok;
void read(int &x){
for (ok=,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=;
for (x=;isdigit(ch);x=x*+ch-'',ch=getchar());
if (ok) x=-x;
}
struct Point{int v,id;};
int cnt;
struct node{
Point p;
int pre,next;
}T[maxn<<];
int newnode(Point p,int pre,int next){T[++cnt]=(node){p,pre,next};return cnt;}
struct queue{
int siz,head,tail;
bool empty(){return !siz;}
void push_front(Point p){
if (!siz) head=tail=newnode(p,,);
else T[head].pre=newnode(p,,head),head=T[head].pre;
++siz;
}
void push_back(Point p){
if (!siz) head=tail=newnode(p,,);
else T[tail].next=newnode(p,tail,),tail=T[tail].next;
++siz;
}
void pop_front(){siz--,head=T[head].next;}
void pop_back(){siz--,tail=T[tail].pre;}
Point front(){return T[head].p;}
Point back(){return T[tail].p;}
}list[maxn<<];
int tot,now[maxn<<],pre[maxn<<];
Point point[maxn<<];
int n,m,last,val[maxn],sum[maxn],rest[maxn];
void add(int u,Point p){pre[++tot]=now[u],now[u]=tot,point[tot]=p;}
int calc(){
int ans=;
for (int i=n;i>=;i--){
if (!sum[i]) ans++,rest[i]=;
rest[i]+=rest[i+];
}
if (ans>=m) return ; else return ;
}
void push(int u,Point p){
while (!list[u].empty()&&p.v<list[u].back().v) list[u].pop_back();
list[u].push_back(p);
}
Point calc(int u,int lim){
for (int p=now[u];p&&point[p].id<=lim;p=pre[p]) push(u,point[p]),now[u]=p;
while (!list[u].empty()&&list[u].front().id<=last) list[u].pop_front();
return list[u].empty()?(Point){maxn,maxn}:list[u].front();
}
Point min(Point a,Point b){return a.v<b.v?a:b;}
int main(){
read(n),read(m);
for (int i=;i<=n;i++) read(val[i]),read(sum[i-]),sum[i-]=(sum[i-])?:-;
for (int i=n-;i>=;i--) sum[i]+=sum[i+];
for (int i=n;i>=;i--) add(sum[i]+base,(Point){val[i],i});
int S=sum[],d=(S!=)?(int)ceil(1.0*abs(S)/(1.0*m)):calc();
if (d){
for (int i=;i<m;i++){
Point ans=(Point){maxn,maxn};
for (int j=S-d+base;j<=S+d+base;j++){
if (ceil(abs(1.0*j-base)/(1.0*m-i))<=d)
ans=min(ans,calc(j,n-(m-i)));
}
printf("%d ",ans.v);
last=ans.id,S=sum[last];
}
printf("%d\n",val[n]);
}
else{
for (int i=,p=now[base];i<m;i++){
for (;p&&rest[point[p].id]->=m-i;p=pre[p]) push(base,point[p]);
printf("%d ",list[base].front().v);
list[base].pop_front();
}
printf("%d\n",val[n]);
}
return ;
}

bzoj3141: [Hnoi2013]旅行的更多相关文章

  1. BZOJ3141 Hnoi2013 游走 【概率DP】【高斯消元】*

    BZOJ3141 Hnoi2013 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点 ...

  2. BZOJ3141:[HNOI2013]旅行

    浅谈队列:https://www.cnblogs.com/AKMer/p/10314965.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem.p ...

  3. 3141: [Hnoi2013]旅行 - BZOJ

    Description Input 第一行为两个空格隔开的正整数n, m,表示旅行的城市数与旅行所花的月数.接下来n行,其中第 i行包含两个空格隔开的整数Ai和Bi,Ai表示他第i个去的城市编号.Bi ...

  4. HNOI2013旅行

    一道欺负我智商的题... 本来想打单调队列优化dp的,结果看到算法标签就点了此题 洛谷题面 首先你要理解题意,蒟蒻理解了好久.它就是说,给你一个由1和-1组成的数列,让你分成m段,并让这m段区间和最大 ...

  5. 【LG3229】[HNOI2013]旅行

    题面 洛谷 题解 勘误:新的休息点a需要满足的条件2为那一部分小于等于ans 代码 \(100pts\) #include <iostream> #include <cstdio&g ...

  6. Hnoi2013题解 bzoj3139~3144

    话说好久没写题(解)了.. 先贴份题解:http://wjmzbmr.com/archives/hnoi-2013-%E9%A2%98%E8%A7%A3/(LJ神题解..Lazycal表示看不懂..) ...

  7. [HNOI2013]题解

    代码在最后 [HNOI2013]比赛 记忆化搜索 把每一位还需要多少分用\(27\)进制压进\(long\) \(long\),\(map\)记忆化一下即可 [HNOI2013]消毒 先考虑在二维平面 ...

  8. # HNOI2012 ~ HNOI2018 题解

    HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...

  9. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

随机推荐

  1. 趣味理解ADO.NET对象模型

    为了更好地理解ADO.NET的架构模型的各个组成部分,我们可以对ADO.NET中的相关对象进行图示理解,如图所示的是ADO.NET中数据库对象的关系图. 讲究完关系图后,为了加深大家的理解,我们可以用 ...

  2. IOS 表视图UITableView 束NSBundle

    今天搞了一下表视图UITableView 表视图是在以后应用程序开发中经常用到的一个视图,所以必须要熟练掌握 所获不多,对视图有了一个大概的了解 其中有用到NSBundle , 束   这个类 先说一 ...

  3. 【设计模式 - 5】之适配器模式(Adapter)

    1      模式简介 适配器模式解决的问题:让原本因为接口不兼容而不能一起工作的类可以一起工作. 适配器模式的UML原理图如下图所示: 从上图可见,客户想要用Target接口实现Adaptee接口中 ...

  4. All About JAVA Maven的安装

    一转眼几个月过去了..真是忙碌的几个月,最近在弄CAS 身份认证系统,新版本的CAS需要使用Maven进行构建,所以还要研究下Maven相关的资料.第一步就是下载安装Maven.根据官方网站的文档很容 ...

  5. linux lsof命令详解

    linux lsof命令详解 简介 lsof(list open files)是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访 ...

  6. 趣谈iOS运行时的方法调用原理

    一个成熟的计算机语言必然有丰富的体系,复杂的容错机制,处理逻辑以及判断逻辑.但这些复杂的逻辑都是围绕一个主线丰富和展开的,所以在学习计算机语言的时候,先掌握核心,然后了解其原理,明白程序语言设计的实质 ...

  7. IIS注册.net框架及temp文件权限开放

    配置好IIS服务之后,在浏览器打开localhost:xx[端口号],提示:无法识别属性 targetFramework=4.0 这是因为项目是4.0框架,配置IIS时,在应用程序池没有选择.net ...

  8. Erlang - Download and Install for Linux

    1. 下载 Erlang [huey@huey-K42JE erlang]$ wget http://www.erlang.org/download/otp_src_R16B03.tar.gz 2. ...

  9. JSP自定义标签库

    总所周知,JSP自定义标签库,主要是为了去掉JSP页面中的JAVA语句 此处以格式化输出时间戳为指定日期格式为例,简单介绍下JSP自定义标签的过程. 编写标签处理类(可继承自javax.servlet ...

  10. 强制关闭myeclipse出现的问题

    重启时,可能会出现打不开关闭前所在的workspace.其他workspace可以正常打开. 今天遇到这个问题,以前就遇到过,但是忘记如何解决了.今天在我等了十多分钟后,神奇的myeclipse自己起 ...