Lightning Conductor

link

化一下式子:

\[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;
}
posted @ 2022-04-30 16:56  Feyn618  阅读(31)  评论(0编辑  收藏  举报