bzoj3141: [Hnoi2013]旅行
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
2 0
3 1
4 1
1 0
5 0
6 1
7 1
8 0
Sample Output
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]旅行的更多相关文章
- BZOJ3141 Hnoi2013 游走 【概率DP】【高斯消元】*
BZOJ3141 Hnoi2013 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点 ...
- BZOJ3141:[HNOI2013]旅行
浅谈队列:https://www.cnblogs.com/AKMer/p/10314965.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem.p ...
- 3141: [Hnoi2013]旅行 - BZOJ
Description Input 第一行为两个空格隔开的正整数n, m,表示旅行的城市数与旅行所花的月数.接下来n行,其中第 i行包含两个空格隔开的整数Ai和Bi,Ai表示他第i个去的城市编号.Bi ...
- HNOI2013旅行
一道欺负我智商的题... 本来想打单调队列优化dp的,结果看到算法标签就点了此题 洛谷题面 首先你要理解题意,蒟蒻理解了好久.它就是说,给你一个由1和-1组成的数列,让你分成m段,并让这m段区间和最大 ...
- 【LG3229】[HNOI2013]旅行
题面 洛谷 题解 勘误:新的休息点a需要满足的条件2为那一部分小于等于ans 代码 \(100pts\) #include <iostream> #include <cstdio&g ...
- Hnoi2013题解 bzoj3139~3144
话说好久没写题(解)了.. 先贴份题解:http://wjmzbmr.com/archives/hnoi-2013-%E9%A2%98%E8%A7%A3/(LJ神题解..Lazycal表示看不懂..) ...
- [HNOI2013]题解
代码在最后 [HNOI2013]比赛 记忆化搜索 把每一位还需要多少分用\(27\)进制压进\(long\) \(long\),\(map\)记忆化一下即可 [HNOI2013]消毒 先考虑在二维平面 ...
- # HNOI2012 ~ HNOI2018 题解
HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
随机推荐
- redux-applyMiddleware实现理解+自定义中间件
前言: 终于好好理解了middleware.... 1.redux middleware提供的是位于 action 被发起之后,到达 reducer 之前的扩展点. redux通过store.disp ...
- CAS学习笔记(三)—— SERVER登录后用户信息的返回
一旦CAS SERVER验证成功后,我们就会跳转到客户端中去.跳转到客户端去后,大家想一想,客户端总要获取用户信息吧,不然客户端是怎么知道登录的是哪个用户.那么客户端要怎么获取用户信息呢? 其实验证成 ...
- Cadence 信号完整性(一)-- 仿真步骤3
(2)单击“Identify DC Nets”,弹出“Identify DC Nets”窗口,如图2-6 所示: 图 2-6 Identify DC Nets 窗口 (3)在“Net”列表中选择网络如 ...
- winform 解决界面闪动、提升加载速度 分类: WinForm 2015-02-03 16:34 161人阅读 评论(0) 收藏
说明: 从一个技术交流群里获得,经验证效果不错. //作用 加快界面加载 protected override CreateParams CreateParams { ...
- myNote
源码地址 :http://450640526.ys168.com/ 编辑器是WEBBWOSER制作的 你的Internet Explorer的版本至少要是8.0的否则用不了 还有很多BUG 很多功能没 ...
- [Javascript] Manage Application State with Immutable.js
Learn how Immutable.js data structures are different from native iterable Javascript data types and ...
- cocos2d-x3.0-结合TH脚本引擎
近期自己在研究手机游戏开发,呵呵.引擎就选择了cocos2d-x,略微看了下感觉好像非常不错的样子. 写个一般的游戏,全然能够了.工作量也不会非常大,相对来说开发非常轻松了. 在脚本引擎的选择其中,当 ...
- IOS--实现滤镜效果的四种方式
IOS–实现滤镜效果 demo地址: https://github.com/AbeDay/ios–.git 使用CIFilter来完成IOS中滤镜效果 在IOS中可以使用系统自带的方法来达到路径效果: ...
- (转)if语句优化
一.使用常见的三元操作符 if (foo) bar(); else baz(); ==> foo?bar():baz(); if (!foo) bar(); else baz(); ==> ...
- img标签块状与内联的博弈
新手,请前辈们不吝赐教 说到html中img标签是内联还是块状元素,我们首先要知道什么是内联(inline),什么又是块状(block)? 我也在网上查看了一些别人分享的经验,有一个讲到了文档流的概念 ...