【BZOJ2792】[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次。

题解:容易想到二分答案,但是如何判定是个问题。我们先不考虑xk=0的要求,我们先正着反着扫两遍序列,将相邻两项差>mid的改掉,即可满足任意相邻的两项差都不超过mid。

然后我们枚举k,看一下如果xk=0会对那些数产生影响。如果xk=0,那么k左右两边的数就会形成两个公差为mid的等差数列向外延伸,一直延伸到该位置的数比等差数列对应的数要小为止。所以每个数的影响范围都是一段区间[l,r],并且容易发现k越大l越大,k越小r越小。所以我们可以用双指针处理出每个数影响区间的左端点和右端点,最后扫一遍得到最小的k即可。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn=1000010;
int n,ans;
int v[maxn],x[maxn],ls[maxn],rs[maxn];
ll m;
ll s[maxn],s1[maxn],s2[maxn];
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
inline bool check(int mid)
{
ll i,j,sum=0;
for(i=1;i<=n;i++)
{
v[i]=x[i];
if(i>1) v[i]=min(v[i],v[i-1]+mid);
}
for(i=n-1;i>=1;i--) v[i]=min(v[i],v[i+1]+mid);
s1[n+1]=s2[0]=1ll<<60;
for(i=1;i<=n;i++) s[i]=s[i-1]+v[i],sum+=x[i]-v[i],s2[i]=min(s2[i-1],v[i]-i*mid);
for(i=n;i>=1;i--) s1[i]=min(s1[i+1],v[i]+i*mid);
for(i=j=1;i<=n;i++)
{
for(;s1[j]<i*mid;j++);
ls[i]=j;
}
for(i=j=n;i>=1;i--)
{
for(;s2[j]<-i*mid;j--);
rs[i]=j;
}
for(i=1;i<=n;i++)
{
if(sum+s[rs[i]]-s[ls[i]-1]-mid*(i-ls[i])*(i-ls[i]+1)/2-mid*(rs[i]-i)*(rs[i]-i+1)/2<=m)
{
ans=i;
return 1;
}
}
return 0;
}
int main()
{
n=rd(),scanf("%lld",&m);
int i,l=0,r=0,mid;
for(i=1;i<=n;i++) x[i]=rd(),r=max(r,x[i]);
check(2);
while(l<r)
{
mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d %d",ans,r);
return 0;
}

最新文章

  1. STL插入删除和查询测试
  2. C# 委托和事件(二):使用.Net框架中的EventArgs和EventHandler
  3. 2.django笔记之缓存,session,cookie,ajax
  4. magento -- 添加新产品时状态默认为激活,库存状态默认为有库存
  5. Oracle数据库——体系结构
  6. SQL SERVER中查询参数为空(null)时默认查询所有的实现
  7. Asp.Net生命周期系列三
  8. handler looper 和 线程
  9. Android 各种MIME类型和文件类型的匹配表
  10. webform基础介绍及页面传值(session,cookie)、跳转页面
  11. 百度SiteApp构建网站APP
  12. C语言之printf函数
  13. opnet的simple_source模块学习 分类: opnet 2014-05-18 09:50 170人阅读 评论(0) 收藏
  14. 如何解决JavaScript中0.1+0.2不等于0.3
  15. live-server 介绍&amp;安装
  16. 利用Grafana展示zabbix数据
  17. Vue2.x源码学习笔记-Vue构造函数
  18. CRM系统(第三部分)
  19. C#设计模式(12)——组合模式
  20. ADO读写DateTime方式

热门文章

  1. 关于flex,好像有12个属性非常重要
  2. unity, do nothing的state
  3. spring概念简介、bean扫描与注册实现方式
  4. 响应式布局框架 Pure-CSS 5.0 示例中文版-下
  5. makefile之strip函数
  6. iOS开发总结-Xcode常见错误
  7. 0071 CentOS_Tomcat访问文件名包含中文的文件出现404错误
  8. js 静态方法 静态变量 实例方法 实例变量
  9. Android开发之Fragment传递參数的几种方法
  10. sama5d36 OUT0-OUT3 对应关系 带光模块的系统