BZOJ 2792 Poi2012 Well 二分答案
题目大意:给定一个非负整数序列
二分答案,然后验证的时候首先让相邻的都不超过
假设某个点须要改成
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 1001001
using namespace std;
int n,pos,a[M];
long long m;
bool Judge(long long limit)
{
long long cost=0;
int i,j;
static int b[M];
for(i=1;i<=n;i++)
b[i]=a[i];
for(i=2;i<=n;i++)
if(b[i]-b[i-1]>limit)
{
cost+=b[i]-b[i-1]-limit;
b[i]=b[i-1]+limit;
}
for(i=n-1;i;i--)
if(b[i]-b[i+1]>limit)
{
cost+=b[i]-b[i+1]-limit;
b[i]=b[i+1]+limit;
}
if(cost>m) return false;
static long long sum[M];
for(i=1;i<=n;i++)
sum[i]=sum[i-1]+b[i];
static int l[M],r[M];
for(j=1,i=1;i<=n;i++)
{
while( b[j]<(long long)(i-j)*limit )
j++;
l[i]=j;
}
for(j=n,i=n;i;i--)
{
while( b[j]<(long long)(j-i)*limit )
j--;
r[i]=j;
}
for(i=1;i<=n;i++)
{
long long _cost=(sum[r[i]]-sum[l[i]-1]);
_cost-=(long long)limit*(i-l[i])*(i-l[i]+1)>>1;
_cost-=(long long)limit*(r[i]-i)*(r[i]-i+1)>>1;
if(cost+_cost<=m)
return pos=i,true;
}
return false;
}
int Bisection()
{
int l=0,r=1000000000;
while(r-l>1)
{
int mid=l+r>>1;
if( Judge(mid) )
r=mid;
else
l=mid;
}
return Judge(l)?l:r;
}
int main()
{
#ifdef PoPoQQQ
freopen("stu_tests\\stu4c.in","r",stdin);
#endif
int i;
cin>>n>>m;
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
int ans=Bisection();
Judge(ans);
cout<<pos<<' '<<ans<<endl;
return 0;
}