HNOI2013旅行
一道欺负我智商的题。。。
本来想打单调队列优化dp的,结果看到算法标签就点了此题
首先你要理解题意,蒟蒻理解了好久。它就是说,给你一个由1和-1组成的数列,让你分成m段,并让这m段区间和最大值最小,还要求多种方案时字典序最小。
我也不知道大佬怎么做的,反正我不会高斯消元。。。
哦,对了,如果输入的是0,表示他不喜欢则那一位为-1。
设总和为S。区间和最小值为ans。后缀和为sum[],后缀中0的个数为cnt[]。
为什么是后缀,往后看。。。
首先考虑特殊情况:
- 全是1 显然答案为ans=ceil(S/m);ceil()是向上取整。
- 全是-1 ans=ceil(abs(S)/m)
- 一半全1,一半全-1 比如11111-1-1-1可以变成11(111-1-1-1),括号里为0,可以与任意区间搭配,于是变成了上面的情况。
所以ans=ceil(abs(S)/m),简易证明:你可以用第三中方法狂消1和-1直到只有一种数,剩下来的数的个数是abs(S)。
如果abs(S)=0且能分的区间不足m那就另当别论。。。
由于我太菜了,还有情况没考虑就多多包含
先预处理sum[],ans,cnt[];
- S=0
- cnt[1]>=m,此时找sum[i]=0的点i,用单调队列维护找出字典序最小的一条即可。
- cnt[1]<m,ans>0,和下面一起处理。
- S!=0 sum的每一种取值分开考虑。
设上一个选的为last,则这一个i能选要满足abs(sum[last+1]-sum[i+1])<=ans,那么我们枚举sum[i+1]的取值时就可以直接从sum[last+1]-ans到sum[last+1]+ans。
并且abs(sum[i+1]/m'(即剩下要选的数量))要满足小于等于ans,i还有后面的数不能超过m'个。
然后跑单调队列就完啦,不要告诉我你切黑题还不会这个。。。
实现起来还有不少细节,比如负数下标之类的,仔细看下应该都能懂
如果你想TLE的话deque走起
#include<cstdio>
#include<algorithm>
const int N=5e5+;
int a[N],sum[N],cnt[N],tot;
struct node
{
int l,r,val;
}p[N<<];
inline int newnode(int l,int r,int val)
{
p[++tot]=(node){l,r,val};
return tot;
}
struct que
{
int start,end,len;
inline void push_back(int x)
{
if(!len)start=end=newnode(,,x);
else p[end].r=newnode(end,,x),end=p[end].r;
++len;
}
inline int empty(){return !len;}
inline int front(){return p[start].val;}
inline int back(){return p[end].val;}
inline void pop_front(){start=p[start].r;--len;}
inline void pop_back(){end=p[end].l;--len;}
inline void push(int x)
{
while(!empty()&&a[back()]>a[x])pop_back();
push_back(x);
}
}dui[N<<],dui1[N<<],*q=dui+N,*q1=dui1+N;
inline int min(const int &x,const int &y)
{return a[x]<a[y]?x:y;}
int main()
{
int n,m,ans;scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)scanf("%d%d",&a[i],&sum[i]),sum[i]=sum[i]?:-;
for(int i=n-;i;--i)sum[i]+=sum[i+];
for(int i=n;i;--i){cnt[i]+=cnt[i+];if(!sum[i])++cnt[i];}
cnt[n+]=-;
// for(int i=1;i<=n+1;++i)printf("%d %d\n",sum[i],cnt[i]);
int s=sum[];
ans=s?(abs(s)-)/m+:cnt[]<m;//printf("ss%d\n",ans);
if(ans)
{
a[n+]=n+;int la=;
for(int i=;i<=n;++i)
q1[sum[i]].push_back(i-);
for(int i=;i<m;++i)
{
int aa=n+;
for(int j=sum[la+]-ans;j<=sum[la+]+ans;++j)
{
if((abs(j)+m-i-)/(m-i)>ans)continue;
while(!q1[j].empty()&&n-q1[j].front()>=m-i){if(q1[j].front()>la)q[j].push(q1[j].front());q1[j].pop_front();}
while(!q[j].empty()&&q[j].front()<=la){q[j].pop_front();}
if(!q[j].empty())aa=min(aa,q[j].front());
}
la=aa;
printf("%d ",a[aa]);
}
}
else
{
for(int i=,j=;i<m;++i)
{
for(;cnt[j+]>=m-i;++j)
if(!sum[j+])
q[].push(j);
printf("%d ",a[q[].front()]);
q[].pop_front();
}
}
printf("%d\n",a[n]);
return ;
}
HNOI2013旅行的更多相关文章
- 3141: [Hnoi2013]旅行 - BZOJ
Description Input 第一行为两个空格隔开的正整数n, m,表示旅行的城市数与旅行所花的月数.接下来n行,其中第 i行包含两个空格隔开的整数Ai和Bi,Ai表示他第i个去的城市编号.Bi ...
- bzoj3141: [Hnoi2013]旅行
Description Input 第 一行为两个空格隔开的正整数n, m,表示旅行的城市数与旅行所花的月数.接下来n行,其中第 i行包含两个空格隔开的整数Ai和Bi,Ai表示他第i个去的城市编号 ...
- 【LG3229】[HNOI2013]旅行
题面 洛谷 题解 勘误:新的休息点a需要满足的条件2为那一部分小于等于ans 代码 \(100pts\) #include <iostream> #include <cstdio&g ...
- BZOJ3141:[HNOI2013]旅行
浅谈队列:https://www.cnblogs.com/AKMer/p/10314965.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem.p ...
- [HNOI2013]题解
代码在最后 [HNOI2013]比赛 记忆化搜索 把每一位还需要多少分用\(27\)进制压进\(long\) \(long\),\(map\)记忆化一下即可 [HNOI2013]消毒 先考虑在二维平面 ...
- Hnoi2013题解 bzoj3139~3144
话说好久没写题(解)了.. 先贴份题解:http://wjmzbmr.com/archives/hnoi-2013-%E9%A2%98%E8%A7%A3/(LJ神题解..Lazycal表示看不懂..) ...
- # HNOI2012 ~ HNOI2018 题解
HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 【BZOJ3143】【HNOI2013】游走 && 【BZOJ3270】博物馆 【高斯消元+概率期望】
刚学完 高斯消元,我们来做几道题吧! T1:[BZOJ3143][HNOI2013]游走 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小 ...
随机推荐
- c++三大概念要分清--重载,隐藏(重定义),覆盖(重写)
重载,隐藏(重定义),覆盖(重写)—这几个名词看着好像很像,不过其实一样都不一样!! 综述: 说明:覆盖中的访问修饰符可以不同是指可以不用显示地用virtual:当访问修饰符改为const或者stat ...
- Flexbox + js实现滑动拼图游戏
滑动拼图就是把一张图片分成几等份,打乱顺序(下图),然后通过滑动拼凑成一张完整的图片. 要实现一个拼图游戏,需要考虑怎样随机的打乱顺序,怎样交换两张图片的位置,等等.但是,使用了Flexbox布局以后 ...
- 硬件设计原理图Checklist 参考案例二 【转载】
类别 描述 检视规则 原理图需要进行检视,提交集体检视是需要完成自检,确保没有低级问题. 检视规则 原理图要和公司团队和可以邀请的专家一起进行检视. 检视规则 第一次原理图发出进行集体检视后所有的修改 ...
- PHP中的文件包含
在PHP中,包含文件有两种方式:include和require.这两种方式的功能一样,只有一个区别,就是使用require包含一个文件时,如果出现错误,脚本不会继续执行:而如果使用include包含, ...
- 第十二次作业psp
psp 进度条 代码累积折线图 博文累积折线图 psp饼状图
- “吃神么,买神么”的第二个Sprint计划(总结)
“吃神么,买神么”项目Sprint计划 ——5.28 星期四(第八天)第一次Spring计划结束 第一阶段Spring的目标以及完成情况: 时间:5月21号~5月28号(7天) 目标:第二阶段主 ...
- 【CS231N】3、Softmax分类器
wiki百科:softmax函数的本质就是将一个K维的任意实数向量压缩(映射)成另一个K维的实数向量,其中向量中的每个元素取值都介于(0,1)之间. 一.疑问 二.知识点 1. softmax函数公式 ...
- C#代码分析(第三周)
阅读下面程序,请回答如下问题: 问题1:这个程序要找的是符合什么条件的数? 问题2:这样的数存在么?符合这一条件的最小的数是什么? 问题3:在电脑上运行这一程序,你估计多长时间才能输出第一个结果?时间 ...
- [2017BUAA软工]第1次个人作业
软工第1次个人作业 一.快速看完整部教材,列出你不懂的5-10个问题,发布在你的个人博客上. 1.文中提到"积累问题领域的知识和经验(例如:对医疗或金融行业的了解)."然而我们如何 ...
- 『编程题全队』Alpha 阶段冲刺博客Day2
1.每日站立式会议 1.会议照片 2.昨天已完成的工作统计 孙志威: 确定了本阶段的团队目标 确定了个人所分配的任务(主要为客户端GUI模块) 孙慧君: 确定了自己的任务,并着手开始环境 ...