P3515 [POI2011]Lightning Conductor[决策单调性优化]

给定一序列,求对于每一个$a_i$的最小非负整数$p_i$,使得$\forall j \neq i $有$ p_i>=a_j-a_i+ \sqrt{|i-j|}$。


绝对值很烦 ,先分左右情况单独做。现在假设j都在i左边,则$ p_{i} = max \{ a_{j}-a_{i}+ \sqrt{i-j} \} = max \{ a_{j}+ \sqrt{i-j} \} - a_i$。带根号,不易斜率优化,考虑证决策单调性。

假设最优决策为j,j之前的任意决策称之为$j'$,只与$j$有关的项令之为$h[j]=a[j]$,则有

$h[j]+\sqrt{i-j} \geqslant h[j']+\sqrt{i-j'}$  ①

现要证$ h[j]+\sqrt{i-j+1} \geqslant h[j']+\sqrt{i-j'+1}$ ②

即证$ \sqrt{i-j+1}-\sqrt{i-j} \geqslant \sqrt{i-j'+1}-\sqrt{i-j'}$($②-①$得)

那么把它看成关于$j$的函数看单调性,设$g(j)=\sqrt{i-j+1}+\sqrt{i-j}$

对其求导。

$g'(j)=[(i-j+1)^{\frac{1}{2}}]' - [(i-j)^{\frac{1}{2}}]'=-\frac{1}{2} (i-j+1)^{-\frac{1}{2}} + \frac{1}{2} (i-j)^{-\frac{1}{2}}=\frac{1}{2} (\frac{1}{\sqrt{i-j}}-\frac{1}{\sqrt{i-j+1}})$

由$ i-j<i-j+1$知$\frac{1}{2} (\frac{1}{\sqrt{i-j}}-\frac{1}{\sqrt{i-j+1}}) > 0$则函数$g(j)$单调增,则上不等式成立,满足单调性。

证完决策单调性优化即可。


错误记录:第二次写的时候line37写成l<r了,,丢人。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef double db;
 5 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
 6 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
 7 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
 8 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
 9 template<typename T>inline T read(T&x){
10     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
11     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
12 }
13 const int N=500000+7;
14 struct kochiya_sanae{
15     int l,r,pos;
16     kochiya_sanae(int l0=0,int r0=0,int pos0=0):l(l0),r(r0),pos(pos0){}
17 }q[N];
18 db sq[N],f[N],h[N];
19 int n,l,r;
20 inline void preprocess(){for(register int i=1;i<=n;++i)sq[i]=sqrt((db)i);}
21 inline db calc(int j,int i){return (db)h[j]+sq[i-j];}
22 inline int find_pos(int L,int R,int j,int i){
23     ++R;int mid;
24     while(L<R){
25         mid=L+R>>1;
26         if(calc(j,mid)<=calc(i,mid))R=mid;
27         else L=mid+1;
28     }
29     return R;
30 }
31 inline void dp(){
32     q[l=r=1]=kochiya_sanae(0,n,0);
33     for(register int i=1;i<=n;++i){
34         if(q[l].r<i)++l;else ++q[l].l;
35         MAX(f[i],calc(q[l].pos,i)-h[i]);
36         while(l<=r&&calc(q[r].pos,q[r].l)<=calc(i,q[r].l))--r;
37         if(r<l)q[r=l]=kochiya_sanae(i,n,i);
38         else{
39             int k;
40             if(calc(q[r].pos,q[r].r)>calc(i,q[r].r))k=q[r].r+1;
41             else k=find_pos(q[r].l,q[r].r,q[r].pos,i);
42             if(k<=n)q[r].r=k-1,q[++r]=kochiya_sanae(k,n,i);
43         }
44     }
45 }
46 
47 int main(){//freopen("tmp.in","r",stdin);freopen("tmp.out","w",stdout);
48     read(n);for(register int i=1;i<=n;++i)read(h[i]);h[0]=-3;
49     preprocess();dp();reverse(h+1,h+n+1);reverse(f+1,f+n+1);dp();
50     for(register int i=n;i;--i)printf("%d\n",(int)ceil(f[i]));
51     return 0;
52 }

 

posted @ 2019-03-04 08:14  Ametsuji_akiya  阅读(229)  评论(0编辑  收藏  举报