Lightning Conductor
化一下式子:
\[a_j\le a_i+p-\sqrt{|i-j|}
\]
\[p\ge a_j-a_i+\sqrt{|i-j|}
\]
会发现 \(-a_i\) 是定值,剩下的是一些只由 \(ij\) 决定的一次贡献函数,再考虑到可可爱爱的数据范围 (\(1\le N\le5\times10^5\)),想到用决策单调性来优化。
正确性?鬼球知道为什么是这样。证明嘛题解区有,但我懒得去看,上午就是为了看那个什么自然数幂之和耗了一个小时而没有卵用……
考虑把方程拆成\(i\le j\) 和\(j\le i\) 两个部分,因为方程里带绝对值的一般不怎么单调。于是我们得到了两个新的方程,对这两个方程进行DP求更大值即可。
由于没有严格的求解顺序此题可以使用分治的写法。二分栈的写法理论上也是行得通的,懒得敲了。
#include<cstdio>
#include<cmath>
#define zczc
const int N=500010;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w>='0'&&w<='9'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
inline int max(int s1,int s2){
return s1<s2?s2:s1;
}
inline void swap(int &s1,int &s2){
int s3=s1;s1=s2;s2=s3;return;
}
int m,a[N],ans[N];
bool kk;
double cost(int s1,int s2){
if(s1>s2)return -1;
return -a[s2]+a[s1]+sqrt((double)s2-s1);
}
void solve(int ql,int qr,int al,int ar){
if(al==ar){
if(kk)for(int i=ql;i<=qr;i++)ans[m-i+1]=max(ans[m-i+1],ceil(cost(al,i)));
else for(int i=ql;i<=qr;i++)ans[i]=max(ans[i],ceil(cost(al,i)));
return;
}
if(ql>qr)return;
double now=-1;int pl,mid=ql+qr>>1;
for(int i=al;i<=ar;i++){
double nv=cost(i,mid);
if(nv>now){now=nv;pl=i;}
}
if(kk)ans[m-mid+1]=max(ans[m-mid+1],ceil(now));
else ans[mid]=max(ans[mid],ceil(now));
solve(ql,mid-1,al,pl);
solve(mid+1,qr,pl,ar);
}
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
read(m);
for(int i=1;i<=m;i++)read(a[i]);
solve(1,m,1,m);
for(int i=1;i*2<=m;i++)swap(a[i],a[m+1-i]);kk=true;
solve(1,m,1,m);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}
一如既往,万事胜意