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
",(int)ceil(dp[i])-a[i]);   
    return 0; 
}          

  

原文地址:https://www.cnblogs.com/guangheli/p/12597335.html