Loading

[题解]P3515 [POI 2011] Lightning Conductor

题目简述

给定 \(n\) 个建筑物排成一行,编号从 \(1\)\(n\)。第 \(i\) 个建筑物的高度为 \(h_i\)。若在建筑物 \(i\) 的屋顶放置一个高度为 \(p\) 的避雷针,则它能保护建筑物 \(j\) 当且仅当满足不等式:

\[h_j \leq h_i + p - \sqrt{|i - j|} \]

其中 \(|i - j|\) 表示 \(i\)\(j\) 之差的绝对值。

对于每个建筑物 \(i\),求一个非负整数 \(p_i\),表示放置在建筑物 \(i\) 上且能保护所有建筑物的避雷针的最小高度。

思路

对于单个方向:变形:\(k = \max \{ h_j + \sqrt{|i - j|} \} - h_i \quad (j < i)\)

那么问题转换为对于每个 \(i\),找前边的 \(h_j + \sqrt{|i - j|}\) 的最大值,然后这个式子显然满足决策单调性,就直接分治解决 \([1, n]\)\(mid\) 的最优决策点 \(p\),对于 \([1, mid-1]\) 的中点继续找范围为 \([1, p]\) 的最优决策点,对于 \([mid + 1, r]\) 的中点继续找范围为 \([p, n]\) 的最优决策点,以此类推。最后减去 \(h_i\) 并且在正向和逆向中取最大值就是答案了。

代码

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int N=1e6+10;
int n,h[N],f[N];
double w(int i,int j){return 1.0*h[i]+sqrt(1.0*(abs(i-j)));}
void solve(int l,int r,int optl,int optr)
{
	if(l>r)return;
	int mid=(l+r)>>1,p=optl;
	for(int i=optl;i<=min(optr,mid);i++)
		if(w(i,mid)>w(p,mid))p=i;
	f[mid]=max(f[mid],(int)ceil(w(p,mid)));
	solve(l,mid-1,optl,p);
	solve(mid+1,r,p,optr);
}
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)cin>>h[i];
	solve(1,n,1,n);
	reverse(h+1,h+1+n);
	reverse(f+1,f+1+n);
	solve(1,n,1,n);
	reverse(h+1,h+1+n);
	reverse(f+1,f+1+n);
	for(int i=1;i<=n;i++)
		cout<<f[i]-h[i]<<endl;
	return 0;
}

posted @ 2026-03-05 22:07  TommyJin  阅读(2)  评论(0)    收藏  举报