一道欺负我智商的题。。。

本来想打单调队列优化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旅行的更多相关文章

  1. 3141: [Hnoi2013]旅行 - BZOJ

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

  2. bzoj3141: [Hnoi2013]旅行

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

  3. 【LG3229】[HNOI2013]旅行

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

  4. BZOJ3141:[HNOI2013]旅行

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

  5. [HNOI2013]题解

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

  6. Hnoi2013题解 bzoj3139~3144

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

  7. # HNOI2012 ~ HNOI2018 题解

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

  8. bzoj AC倒序

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

  9. 【BZOJ3143】【HNOI2013】游走 && 【BZOJ3270】博物馆 【高斯消元+概率期望】

    刚学完 高斯消元,我们来做几道题吧! T1:[BZOJ3143][HNOI2013]游走 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小 ...

随机推荐

  1. 国密算法--Openssl 实现国密算法(加密和解密)

    上一次讲了产生密钥,这次我们讲一下加密解密的实现. 先说一下加密解密的流程,一下这些内容都是从国密局发布的国密标准文档里面摘录出来的.大家可以去国密局的网站上自己下载. 下列符号适用于本部分. A,B ...

  2. 【Docker】第五篇 Docker 数据管理

    一.基本介绍 数据管理的原因:Docker中的容器一旦删除,容器本身的rootfs文件系统就会被删除,容器中的所有数据就会被删除.为了对一些需要持久化的数据,不随容器删除而删除,所以我们可以通过多个容 ...

  3. Qt 5.x 开发技巧

    出现unresolved external symbol "public: __thiscall Dialog::Dialog(class QWidget *) 或类似不太合理的错误时,可以 ...

  4. hadoop之定制自己的sort过程

    Key排序 1. 继承WritableComparator 在hadoop之Shuffle和Sort中,可以看到mapper的输出文件spill文件需要在内存中排序,并且在输入reducer之前,不同 ...

  5. 机器学习(一):记一次k一近邻算法的学习与Kaggle实战

    本篇博客是基于以Kaggle中手写数字识别实战为目标,以KNN算法学习为驱动导向来进行讲解. 写这篇博客的原因 什么是KNN kaggle实战 优缺点及其优化方法 总结 参考文献 写这篇博客的原因 写 ...

  6. centos安装eclise启动报错

    A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be avail http://blog.csdn.net/u0 ...

  7. Beta发布 _thunder_文案+美工展示

    作业要求:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/1366 团队介绍:thunder 组成员及各位博客地址: 1.王航:htt ...

  8. Notes of Daily Scrum Meeting(11.3)

    Notes of Daily Scrum Meeting(11.3) 2014年11月3日  星期一  20:00—20:30 团队成员 今日团队任务 当日工作分配额 完成情况 陈少杰 阅读理解代码中 ...

  9. Java实验五(客户端)

    一.    实验内容 1.    运行教材上TCP代码,结对进行,一人服务器,一人客户端: 2.    利用加解密代码包,编译运行代码,客户端加密,服务器解密: 3.    客户端加密明文后将密文通过 ...

  10. 剑指offer:用两个栈实现队列

    题目描述: 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路: 可以用stack1来存所有入队的数.在出队操作中,首先将stack1中的元素清空,转移到sta ...