浅谈队列:https://www.cnblogs.com/AKMer/p/10314965.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3141

很好的一道单调队列题……

先把\(0\)变成\(-1\),然后\(sum_i\)表示\([i,n]\)的后缀和。

首先考虑子段和最大值最小是多少。

首先,答案最小不会小于\(\lceil \frac{|sum_1|}{m}\rceil\)

其次,假设相邻的\(1\)或\(-1\)全部合并在一起变成\(0\)抵消掉(因为不管放在哪一段都无影响),留下\(|sum_1|\)个\(1\)或\(-1\),直接均分,刚好可以使最大值是\(\lceil \frac{|sum_1|}{m}\rceil\),所以答案就是这个玩意儿。

但是当\(sum_1\)等于\(0\)且后缀和为\(0\)的\(pos\)个数小于\(m\)时答案就是\(1\),因为分不出那么多段。

在知道答案后,我们再分情况讨论字典序:

当答案等于\(0\)时,直接把后缀和等于\(0\)的前一个点拎出来用单调队列搞搞就行。

当答案不等于\(0\),我们考虑假设第\(i\)段结尾的是\(lst\),那么第\(i+1\)段结尾处后一个位置的后缀和\(s\)要满足\(|sum[lst+1]-s|\leqslant ans\)。

展开一下:\(sum[lst+1]-ans\leqslant s \leqslant sum[lst+1]+ans\)

然后对于每种不同的后缀和维护一个单调队列即可。

每次根据上面的等式枚举下一个\(s\),然后对于子问题\(\lceil\frac{|s|}{m-i}\rceil\)不会超过全局问题的答案,并且后面够分\(m-i\)段,就把他丢到对应的单调队列里面。然后对于每个单调队列的队头拿出来比较选最好的一个就行了。

为啥要开多个单调队列而不是用一个单调队列呢?因为对于每个子问题,所满足的后缀和\(s\)并不一样,不能用当前子问题的\(s'\)把\(s''\)的队头弹掉了,万一下一次只支持\(s''\)而不支持\(s'\)并且之前被你弹掉的那个就是答案呢?

剩下的细节见代码吧。

时间复杂度:\(O(n\sqrt{n})\)

空间复习度:\(O(n)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;const int maxn=1e6+6;int n,m,ans,num,val;
int id[maxn],like[maxn],sum[maxn],cnt[maxn];
int tot[maxn],tmp[maxn],list[maxn],stk[maxn];int read() {int x=0,f=1;char ch=getchar();for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';return x*f;
}struct Queue {int head,tail;void push_back(int pos) {while(head!=tail&&id[list[tail-1]]>id[pos])tail--;list[tail++]=pos;}int front() {return list[head];}void pop_front() {if(head!=tail)head++;}bool empty() {return head==tail;}
}alpha[maxn<<1],*q=alpha+maxn;struct Stack {int tp,cnt;void push_back(int pos) {cnt++;stk[++tp]=pos;}bool empty() {return !cnt;}int top() {return stk[tp];}void pop() {tp--;cnt--;}
}beta[maxn<<1],*s=beta+maxn;int main() {n=read(),m=read();for(int i=1;i<=n;i++)id[i]=read(),like[i]=read();for(int i=n;i;i--) {like[i]-=(!like[i]);tmp[i]=sum[i]=sum[i+1]+like[i];cnt[i]=cnt[i+1]+(!sum[i]);}ans=sum[1]?(abs(sum[1])+m-1)/m:cnt[1]<m;if(!ans) {for(int i=1,j=2;i<m;i++) {for(;j<=n&&cnt[j+1]>=m-i;j++)if(!sum[j+1])q[0].push_back(j);int res=q[0].front();q[0].pop_front();printf("%d ",id[res]);}}else {sort(tmp+1,tmp+n+1);num=unique(tmp+1,tmp+n+1)-tmp-1;for(int i=1;i<=n;i++)tot[lower_bound(tmp+1,tmp+num+1,sum[i])-tmp]++;for(int i=1;i<=num;i++) {s[tmp[i]].tp=val;q[tmp[i]].head=q[tmp[i]].tail=val;val+=tot[i];}int lst=0;id[n+1]=n+1;for(int i=n;i>1;i--)s[sum[i]].push_back(i-1);for(int i=1;i<m;i++) {int res=n+1;for(int j=sum[lst+1]-ans;j<=sum[lst+1]+ans;j++) {if((abs(j)+m-i-1)/(m-i)>ans)continue;while(!s[j].empty()&&n-s[j].top()>=m-i) {if(s[j].top()>lst)q[j].push_back(s[j].top());s[j].pop();}while(!q[j].empty()&&q[j].front()<=lst)q[j].pop_front();if(!q[j].empty()&&id[q[j].front()]<id[res])res=q[j].front();}lst=res;printf("%d ",id[res]);}}printf("%d\n",id[n]);return 0;
}

转载于:https://www.cnblogs.com/AKMer/p/10352869.html

BZOJ3141:[HNOI2013]旅行相关推荐

  1. bzoj3141: [Hnoi2013]旅行

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

  2. [bzoj3141][HNOI2013]旅行

    题目描述 在遥远的HX 国,住着一个旅行家小L,他希望骑着他的自行车游遍全国.在这个国家中,每个城市都有一个编号,共有n 个城市,编号从1 到n.有的城市没有小L 想去的景点,而有的城市有且仅有一个小 ...

  3. # HNOI2012 ~ HNOI2018 题解

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

  4. 2022-2028年中国在线旅行预订市场投资分析及前景预测报告

    [报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了在线旅行行业相关概述.中国在线旅行行业运行环境.分析了中国在线旅行行 ...

  5. LeetCode简单题之旅行终点站

    题目 给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中 paths[i] = [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi .请你找出 ...

  6. usaco Cow Tours 牛的旅行

    Cow Tours 牛的旅行 农民 John 的农场里有很多牧区.有的路径连接一些特定的牧区.一片所有连通的牧区称为一个牧场. 但是就目前而言,你能看到至少有两个牧区不连通.这样,农民 John 就有 ...

  7. gatsby_如何使用Gatsby和Leaflet创建夏季公路旅行地图绘制应用程序

    gatsby Get ready for the summer by building your own road trip mapping app with this step-by-step gu ...

  8. 汉印标签打印机app_旅行一族福音 汉印CP4000L便携照片打印机体验

    最近一段时间,有个问题经常在我脑海中出现:"我们为什么需要打印照片?" 不过没想到,让我瞬间解除这个疑惑的,却是近期刚刚上市的一款便携照片打印机-汉印CP4000L.自从知晓这款产 ...

  9. 2D景观转3D风景大片,无惧复杂光线与遮挡,人类离「躺着旅行」的梦想又近了一步...

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 整理:公众号@机器之心 本文仅做学术分享,如有侵权,请联系删除. 万物皆可转 3D. 上班的时候想旅行 ...

最新文章

  1. Java方法详细介绍
  2. 谢尔盖.布林的早期思想_谷歌联合创始人谢尔盖·布林(Sergey Brin)谈人工智能与自动化...
  3. 暑期集训3:几何基础 练习题C: POJ - 1269
  4. ZOJ.3551.Bloodsucker(期望DP)
  5. unity 多台 显示器 控制_飞利浦292E2E评测丨宽屏显示器中的多面手
  6. C# Winform控件动态删除
  7. 华为腾讯众安微众360大咖齐聚,2019中国区块链开发者大会首批议程曝光!
  8. Centos下安装minikube
  9. c++标准程序库:STL容器之map
  10. linux fb设备驱动,Linux FB 驱动讲解
  11. 2020最新Java高级工程师学习路线
  12. 贴片电阻、贴片电容规格、封装、尺寸
  13. CSDI2018广州关于《Nginx》的分享(附文字速录与PPT)
  14. 分享:无版权图片素材免费下载网站
  15. Python&Opencv手势识别系统(完整源码&自定义UI操作界面&视频教程)
  16. 官方JwPlayer去水印步骤
  17. 内部收益率(二分法)
  18. 异步电机三相电流滞环矢量控制
  19. python 机器学习(引言-莺尾花分类)
  20. win10 计算机网络,win10网络发现已关闭网络计算机和设备不可见怎么办?

热门文章

  1. 想精通 Python 数据挖掘?清华博士带你入门!
  2. python能写app吗_Python可以开发APP吗?
  3. 地级市各产业从业人数数据集(1999-2018年)
  4. 《计算机系统基础》——计算机系统导论
  5. db2top操作手册
  6. nagios 服务端与客户端监控安装与详细配置,各配置文件详解
  7. 【java】莱布尼兹公式求解pi值
  8. python二维数组去重复_python 去除二维数组/二维列表中的重复行方法
  9. 逻辑值分类True False
  10. 【数学】幂运算与快速幂取余