洛谷 P3515 [ POI 2011 ] Lightning Conductor —— 决策单调性DP

时间:2022-07-05 21:36:13

题目:https://www.luogu.org/problemnew/show/P3515

决策单调性...

参考TJ:https://www.cnblogs.com/CQzhangyu/p/7258256.html

注释WA???最近似乎总是WA在二分上...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int const maxn=5e5+;
int n,a[maxn],ans[maxn],h,t;
struct N{
double p,l,r;
N(int p=,int l=,int r=):p(p),l(l),r(r) {}
}q[maxn];
double calc(int i,int j){return a[i]+sqrt(abs(j-i))-a[j];}//i对j的答案
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=,h=,t=;i<=n;i++)
{
while(h<=t&&q[h].r<i)h++;
if(h<=t)q[h].l=i,ans[i]=max(ans[i],(int)ceil(calc(q[h].p,i)));
if(h>t||calc(i,n)>calc(q[t].p,n))
{
while(h<=t&&calc(i,q[t].l)>calc(q[t].p,q[t].l))t--;
if(h<=t)
{
// int l=q[t].l,r=q[t].r,ret;
// while(l<=r)
// {
// int mid=((l+r)>>1);
// if(calc(i,mid)>=calc(q[t].p,mid))ret=mid,r=mid-1;
// else l=mid+1;
// }
// q[t].l=ret-1; q[++t]=N(i,ret,n);
int l=q[t].l,r=q[t].r+;
while(l<r)
{
int mid=((l+r)>>);
if(calc(i,mid)<calc(q[t].p,mid))l=mid+;
else r=mid;
}
q[t].r=l-; q[++t]=N(i,l,n);
}
else q[++t]=N(i,i+,n);
}
}
for(int i=n,h=,t=;i;i--)
{
while(h<=t&&q[h].l>i)h++;
if(h<=t)q[h].r=i,ans[i]=max(ans[i],(int)ceil(calc(q[h].p,i)));
if(h>t||calc(i,)>calc(q[t].p,))//
{
while(h<=t&&calc(i,q[t].r)>calc(q[t].p,q[t].r))t--;
if(h<=t)
{
// int l=q[t].l,r=q[t].r,ret;
// while(l<=r)
// {
// int mid=((l+r)>>1);
// if(calc(i,mid)>calc(q[t].p,mid))ret=mid,r=mid-1;
// else l=mid+1;
// }
// q[t].l=ret+1; q[++t]=N(i,1,ret);
int l=q[t].l,r=q[t].r;
while(l<r)
{
int mid=((l+r)>>);
if(calc(i,mid)<calc(q[t].p,mid))r=mid;
else l=mid+;
}
q[t].l=r; q[++t]=N(i,,r-);
}
else q[++t]=N(i,,i-);
}
}
for(int i=;i<=n;i++)printf("%d\n",ans[i]);
return ;
}