LOJ #2157. 「POI2011 R1」避雷针 (决策单调性,整体二分)
新学了一下决策单调性.
对于这道题,我们可以先考虑 $j<i$ 的情况.
然后我们发现随着 $i$ 变大,$i$ 的决策点不可能减小(因为根号函数的增长速率越来越小,所以一旦被赶超上是不可能追回来的)
然后有两种处理方式:单调队列+二分 or 整体二分.
前者细节较多,后者更好写一些.
code:
#include <bits/stdc++.h>
#define ll long long
#define N 500007
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int a[N],n;
double sqr[N],dp[N];
void getsqr()
{
for(int i=1;i<=n;++i)
sqr[i]=sqrt(i);
}
void cdq(int l,int r,int L,int R)
{
if(l>r) return;
int mid=(l+r)>>1,j0=0;
double mx=0,tmp;
for(int j=L;j<=mid&&j<=R;++j)
{
tmp=a[j]+sqr[mid-j];
if(tmp>mx) mx=tmp,j0=j;
}
dp[mid]=max(dp[mid],mx);
cdq(l,mid-1,L,j0),cdq(mid+1,r,j0,R);
}
int main()
{
// setIO("input");
scanf("%d",&n);
getsqr();
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
cdq(1,n,1,n);
for(int i=1;i<n-i+1;++i) swap(a[i],a[n-i+1]),swap(dp[i],dp[n-i+1]);
cdq(1,n,1,n);
for(int i=n;i;--i) printf("%d\n",(int)ceil(dp[i])-a[i]);
return 0;
}

浙公网安备 33010602011771号