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; }