BZOJ_2792_[Poi2012]Well_二分答案

Description

给出n个正整数X1,X2,...Xn,可以进行不超过m次操作,每次操作选择一个非零的Xi,并将它减一。

最终要求存在某个k满足Xk=0,并且z=max{|Xi - Xi+1|}最小。
输出最小的z和此时最小的k。

Input

第一行两个正整数n, m (1<=n<=1,000,000, 1<=m<=10^18)。第二行n个正整数X1,X2,...Xn (Xi<=10^9)。

Output

输出k和z。数据保证方案一定存在。

Sample Input

16 15
8 7 6 5 5 5 5 5 6 6 7 8 9 7 5 5

Sample Output

1 2

HINT

将X序列变为

0 2 4 5 5 5 5 5 6 6 7 8 9 7 5 5
此时k=1,z=2,共操作了8+5+2=15次。
 

分析:首先肯定要二分答案出z,然后转化为判定是否能用小于等于m次操作使序列满足题意。
假设把第一个位置变成零,那么贪心的让后面比前面高度正好大z,扫一遍即可,可以发现最后的序列有若干个等差数列。
然后考虑怎么推出把其他位置i变成零对答案的贡献,i右边的数会下去一些,i左边的数会上去一些,可以发现这个满足单调性。
设f[i]为把第i个数变为0,左边需要改多少次,g[i]表示右边需要改多少次,双指针扫一遍,找到第一个大于|(j-i)|*z的位置,算出贡献即可。
有个小问题,可能序列一开始是不合法的,这是我们要从左往右再从右往左扫一遍,把不合法的部分削掉。
 
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000050
typedef long long ll;
int n,a[N],b[N],maxx;
ll m,s[N],f[N],g[N];
int check(int p) {
ll re=0;
int i,j;
for(i=1;i<=n;i++) b[i]=a[i];
for(int i=2;i<=n;i++)
if(b[i]-b[i-1]>p)
re+=b[i]-b[i-1]-p,b[i]=b[i-1]+p;
for(int i=n-1;i;i--)
if(b[i]-b[i+1]>p)
re+=b[i]-b[i+1]-p,b[i]=b[i+1]+p;
if(re>m) return 0;
for(i=1;i<=n;i++) s[i]=s[i-1]+b[i];
for(i=1,j=1;i<=n;i++) {
while(j<i&&b[j]<=1ll*(i-j)*p) j++;
f[i]=s[i-1]-s[j-1]-1ll*(i-j)*(i-j+1)/2*p;
}
for(i=n,j=n;i;i--) {
while(j>i&&b[j]<=1ll*(j-i)*p) j--;
g[i]=s[j]-s[i]-1ll*(j-i)*(j-i+1)/2*p;
}
for(i=1;i<=n;i++) if(f[i]+g[i]+b[i]+re<=m) return i;
return 0;
}
int main() {
scanf("%d%lld",&n,&m);
int i;
for(i=1;i<=n;i++) {
scanf("%d",&a[i]);
maxx=max(maxx,a[i]);
}
int l=0,r=maxx+1;
while(l<r) {
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d %d\n",check(l),l);
}

BZOJ_2792_[Poi2012]Well_二分答案的更多相关文章

  1. BZOJ 2792 Poi2012 Well 二分答案

    题目大意:给定一个非负整数序列A.每次操作能够选择一个数然后减掉1,要求进行不超过m次操作使得存在一个Ak=0且max{Ai−Ai+1}最小,输出这个最小值以及此时最小的k 二分答案,然后验证的时候首 ...

  2. [POI2012]STU-Well(二分答案+神仙操作)

    给定一个非负整数序列A,每次操作可以选择一个数然后减掉1,要求进行不超过m次操作使得存在一个Ak=0且max{|Ai−Ai+1|}最小,输出这个最小lk以及最小值. Solution 最大值最小,显然 ...

  3. 【BZOJ2792】[Poi2012]Well 二分+双指针法

    [BZOJ2792][Poi2012]Well Description 给出n个正整数X1,X2,...Xn,可以进行不超过m次操作,每次操作选择一个非零的Xi,并将它减一. 最终要求存在某个k满足X ...

  4. CH Round #72树洞[二分答案 DFS&&BFS]

    树洞 CH Round #72 - NOIP夏季划水赛 描述 在一片栖息地上有N棵树,每棵树下住着一只兔子,有M条路径连接这些树.更特殊地是,只有一棵树有3条或更多的路径与它相连,其它的树只有1条或2 ...

  5. [CF752E]Santa Claus and Tangerines(二分答案,dp)

    题目链接:http://codeforces.com/contest/752/problem/E 题意:给n个橘子,每个橘子a(i)片,要分给k个人,问每个人最多分多少片.每个橘子每次对半分,偶数的话 ...

  6. [NOIP2011] 聪明的质检员(二分答案)

    题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自己的重量 wi 以及价值vi .检验矿产的流程是: 1 .给定m 个区间[L ...

  7. Codeforces Round #377 (Div. 2) D. Exams(二分答案)

    D. Exams Problem Description: Vasiliy has an exam period which will continue for n days. He has to p ...

  8. {POJ}{3897}{Maze Stretching}{二分答案+BFS}

    题意:给定迷宫,可以更改高度比,问如何使最短路等于输入数据. 思路:由于是单调的,可以用二分答案,然后BFS验证.这里用优先队列,每次压入也要进行检查(dis大小)防止数据过多,A*也可以.好久不写图 ...

  9. Leetcode 4 Median of Two Sorted Arrays 二分查找(二分答案+二分下标)

    貌似是去年阿里巴巴c++的笔试题,没有什么创新直接照搬的... 题意就是找出两个排序数组的中间数,其实就是找出两个排序数组的第k个数. 二分答案,先二分出一个数,再用二分算出这个数在两个排序数组排序第 ...

随机推荐

  1. DDD实战进阶第一波(九):开发一般业务的大健康行业直销系统(实现经销商上下文仓储与领域逻辑)

    上篇文章主要讲述了经销商上下文的需求与POCO对象,这篇文章主要讲述该界限上下文的仓储与领域逻辑的实现. 关于界限上下文与EF Core数据访问上下文参考产品上下文相应的实现,这里不再累述. 因为在经 ...

  2. c#之多线程之为所欲为

    一 什么是多线程 1. 什么是进程?一个 exe 运行一次就会产生一个进程,一个 exe 的多个进程之 间数据互相隔离. 2. 一个进程里至少有一个线程:主线程.我们平时写的控制台程序默认就是单线程的 ...

  3. C#将一个枚举里面所有描述和value绑定到下拉列表的方法

    /// <summary> /// 获取枚举值的描述,如果没有描述,则返回枚举名称 /// </summary> /// <param name="en&quo ...

  4. 技术人应该学习的行话--UML统一建模语言

    新生代码农如何在硝烟弥漫的商业丛林中生存和崛起? 洞见,让一部分先遇见未来. 最近公司技术部在组织架构师培训,有幸参与.导师老刘特别推荐了UML语言的学习.回想多年来,自己习惯做一些流程图,框图或者所 ...

  5. 鼠标拖拽定位和DOM各种尺寸详解

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. FOF 全面科普贴(转载)

    看过那么多 FOF 科普贴,这份最全面!告转之~ 来自:https://xueqiu.com/7692591808/81852994 [ 导言 ] 看过那么多FOF科普贴,这份最全面! 昨天下午,青果 ...

  7. 用bootstrap 分页插件问题

    如果页面加载js 一定要记得引入分页的东西 ,不然不会有数据, <script src="${path}/js/bootstrap-paginator.min.js"> ...

  8. IOC 的理解与解释

    IOC 是什么? Ioc-Inversion of Control,即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不 ...

  9. 令状态寄存器访问指令(MRS,MSR)

    ARM中有两条指令用于在状态寄存器和通用寄存器之间传送数据. 针对32位的ARM处理器,状态寄存器就是一个32位长的寄存器.每个位的含义如下图: 分成了4部分: 1,条件标志位 N(Negative) ...

  10. 10个Python练手小程序,学习python的很好的资料

    [程序1] 题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去  掉不满足条件的排列 ...