poi2012 well
stupid_lulu
posted @ 2013年3月26日 01:18
in poi
, 1140 阅读
二分答案+单调队列。。main过了,bzoj无限tle。。。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
int q[1000011];
int n,maxi=0;
int ansx,ansk;
ll m;
int a[1000011];
ll sum[1000011];
ll c[1000011],f[1000011],fr[1000011],fl[1000011],g[1000011];
inline ll min(ll a,ll b){return a<b? a:b;}
inline bool check(int xx){
ll x=xx;
int h=0,t=1;
c[1]=a[1];
q[t]=1;
f[1]=0;
sum[1]=a[1];
for (int i=2;i<=n;i++){
sum[i]=sum[i-1]+a[i];
c[i]=min(c[i-1]+x,a[i]);
while (h<t&&c[q[t]]+x*q[t]>=c[i]+x*i) t--;
int j=q[t];
//printf("i=%d j=%d\n",i,j);
if (h==t){ f[i]=sum[i]-(c[i]+c[i]+(i-1)*x)*i/2;}
else { f[i]=sum[i]-sum[j]-(c[i]+c[i]+(i-j-1)*x)*(i-j)/2+f[j];}
q[++t]=i;
}
//for (int i=1;i<=n;i++) printf("f[%d]=%I64d ",i,f[i]);
//printf("\n");
//for (int i=1;i<=n;i++) printf("c[%d]=%I64d\n",i,c[i]);
h=0; t=1; q[1]=1; fl[1]=a[1];
for (int i=2;i<=n;i++){
while (h+1<t&&c[q[h+2]]+q[h+2]*x<=i*x) h++;
int j=q[h+1];
if (c[q[h+1]]+q[h+1]*x>i*x){fl[i]=sum[i]-(i-1)*x*i/2;}
else {fl[i]=sum[i]-sum[j]-(i-j-1)*x*(i-j)/2+f[j];}
while (h<t&&c[q[t]]+q[t]*x>=c[i]+i*x) t--;
q[++t]=i;
}
//for (int i=1;i<=n;i++) printf("fl[%d]=%I64d ",i,fl[i]);
//printf("\n");
h=0; t=1; c[n]=a[n]; q[t]=n; g[n]=0;
sum[n]=a[n];
for (int i=n-1;i>=1;i--){
sum[i]=sum[i+1]+a[i];
c[i]=min(c[i+1]+x,a[i]);
while (h<t&&c[q[t]]-x*q[t]>=c[i]-x*i) t--;
int j=q[t];
if (h==t){ g[i]=sum[i]-(c[i]+c[i]+(n-i)*x)*(n-i+1)/2;}
else { g[i]=sum[i]-sum[j]-(c[i]+c[i]+(j-i-1)*x)*(j-i)/2+g[j];}
q[++t]=i;
}
//for (int i=1;i<=n;i++) printf("g[%d]=%I64d ",i,g[i]);
//printf("\n");
h=0; t=1; q[1]=n; fr[n]=a[n];
ll ans=fr[n]+fl[n]-a[n];
for (int i=n-1;i>=1;i--){
while (h+1<t&&c[q[h+2]]-q[h+2]*x<=-i*x) h++;
int j=q[h+1];
if (c[q[h+1]]-q[h+1]*x>-i*x){fr[i]=sum[i]-(n-i)*x*(n-i+1)/2;}
else {fr[i]=sum[i]-sum[j]-(j-i-1)*x*(j-i)/2+g[j];}
while (h<t&&c[q[t]]-q[t]*x>=c[i]-i*x) t--;
q[++t]=i;
ans=min(ans,fl[i]+fr[i]-a[i]);
}
//printf("ans=%I64d\n",ans);
if (ans>m) return false;
if (x<ansx){
ansx=x;
for (int i=1;i<=n;i++){
if (fr[i]+fl[i]-a[i]<=m){
ansk=i;
break;
}
}
}
return true;
}
inline void half(int l,int r){
while (l!=r){
int mm=(l+r)/2;
//printf("%I64d\n",mm);
if (check(mm)) r=mm;
else l=mm+1;
}
}
int main(){
//freopen("stu.in","r",stdin);
//freopen("stu.out","w",stdout);
scanf("%d%lld",&n,&m);
ansx=1000000000; ansk=1000000000;
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
maxi=max(maxi,a[i]);
}
//printf("%d\n",maxi);
if (maxi>20000000) maxi=20000000;
half(0,maxi+1);
if (ansx==1000000000) half(20000001,100000000);
printf("%d %d\n",ansk,ansx);
//printf("%d\n",check(1076));
}
评论 (0)