BZOJ3141:[HNOI2013]旅行
浅谈队列: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]旅行相关推荐
- bzoj3141: [Hnoi2013]旅行
Description Input 第 一行为两个空格隔开的正整数n, m,表示旅行的城市数与旅行所花的月数.接下来n行,其中第 i行包含两个空格隔开的整数Ai和Bi,Ai表示他第i个去的城市编号.B ...
- [bzoj3141][HNOI2013]旅行
题目描述 在遥远的HX 国,住着一个旅行家小L,他希望骑着他的自行车游遍全国.在这个国家中,每个城市都有一个编号,共有n 个城市,编号从1 到n.有的城市没有小L 想去的景点,而有的城市有且仅有一个小 ...
- # HNOI2012 ~ HNOI2018 题解
HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...
- 2022-2028年中国在线旅行预订市场投资分析及前景预测报告
[报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了在线旅行行业相关概述.中国在线旅行行业运行环境.分析了中国在线旅行行 ...
- LeetCode简单题之旅行终点站
题目 给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中 paths[i] = [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi .请你找出 ...
- usaco Cow Tours 牛的旅行
Cow Tours 牛的旅行 农民 John 的农场里有很多牧区.有的路径连接一些特定的牧区.一片所有连通的牧区称为一个牧场. 但是就目前而言,你能看到至少有两个牧区不连通.这样,农民 John 就有 ...
- gatsby_如何使用Gatsby和Leaflet创建夏季公路旅行地图绘制应用程序
gatsby Get ready for the summer by building your own road trip mapping app with this step-by-step gu ...
- 汉印标签打印机app_旅行一族福音 汉印CP4000L便携照片打印机体验
最近一段时间,有个问题经常在我脑海中出现:"我们为什么需要打印照片?" 不过没想到,让我瞬间解除这个疑惑的,却是近期刚刚上市的一款便携照片打印机-汉印CP4000L.自从知晓这款产 ...
- 2D景观转3D风景大片,无惧复杂光线与遮挡,人类离「躺着旅行」的梦想又近了一步...
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 整理:公众号@机器之心 本文仅做学术分享,如有侵权,请联系删除. 万物皆可转 3D. 上班的时候想旅行 ...
最新文章
- Java方法详细介绍
- 谢尔盖.布林的早期思想_谷歌联合创始人谢尔盖·布林(Sergey Brin)谈人工智能与自动化...
- 暑期集训3:几何基础 练习题C: POJ - 1269
- ZOJ.3551.Bloodsucker(期望DP)
- unity 多台 显示器 控制_飞利浦292E2E评测丨宽屏显示器中的多面手
- C# Winform控件动态删除
- 华为腾讯众安微众360大咖齐聚,2019中国区块链开发者大会首批议程曝光!
- Centos下安装minikube
- c++标准程序库:STL容器之map
- linux fb设备驱动,Linux FB 驱动讲解
- 2020最新Java高级工程师学习路线
- 贴片电阻、贴片电容规格、封装、尺寸
- CSDI2018广州关于《Nginx》的分享(附文字速录与PPT)
- 分享:无版权图片素材免费下载网站
- Python&Opencv手势识别系统(完整源码&自定义UI操作界面&视频教程)
- 官方JwPlayer去水印步骤
- 内部收益率(二分法)
- 异步电机三相电流滞环矢量控制
- python 机器学习(引言-莺尾花分类)
- win10 计算机网络,win10网络发现已关闭网络计算机和设备不可见怎么办?