1. 程式人生 > >BZOJ 2216: [Poi2011]Lightning Conductor

BZOJ 2216: [Poi2011]Lightning Conductor

難度在於認識到這個式子有決策單調性,原因在於sqrt(a+x)增長速度不斷減慢

單調佇列維護函式,二分求交點

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,a[1000005],stack[1000005];
double F[1000005],s[1000005];
double calc(int x,int y){
	return s[abs(y-x)]+a[x];
}
int check(int x,int y){
	int L=max(x,y),R=n;
	if (calc(x,n)>calc(y,n)) return n+1;
	while (L<R){
		int mid=(L+R)>>1;
		if (calc(x,mid)<=calc(y,mid)) R=mid;
		else L=mid+1;
	}
	return L;
}
void solve(){
	int head=1,tail=0;
	for (int i=1; i<=n; i++){
		while (tail-head>0 && check(stack[tail-1],stack[tail])>=check(stack[tail],i)) tail--;
		stack[++tail]=i;
		while (tail-head>0 && check(stack[head],stack[head+1])<=i) head++;
		F[i]=max(F[i],calc(stack[head],i));
	}
}
int read(){
	char c='-';
	while (c<'0' || c>'9') c=getchar();
	int ans=0;
	while (c>='0' && c<='9'){
		ans=ans*10+c-'0';
		c=getchar();
	}
	return ans;
}
int main(){
	scanf("%d",&n);
	for (int i=1; i<=n; i++) s[i]=sqrt(i);
	for (int i=1; i<=n; i++) a[i]=read();
	solve();
	for (int i=1; i<=n/2; i++) swap(a[i],a[n-i+1]),swap(F[i],F[n-i+1]);
	solve();
	for (int i=n; i>=1; i--) printf("%d\n",max(0,(int)ceil(F[i])-a[i]));
	return 0;
}