【BZOJ2216】[Poi2011]Lightning Conductor 决策单调性

【BZOJ2216】[Poi2011]Lightning Conductor

Description

已知一个长度为n的序列a1,a2,...,an。
对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt(abs(i-j))

Input

第一行n,(1<=n<=500000)
下面每行一个整数,其中第i行是ai。(0<=ai<=1000000000)

Output

n行,第i行表示对于i,得到的p

Sample Input

6
5
3
2
4
2
4

Sample Output

2
3
5
3
5
4

题解:决策单调性不只是斜率优化~

p>=aj-ai+sqrt(abs(i-j)),有绝对值怎么办?拆开讨论两边就行。

你会发现,sqrt函数的增长是越来越慢的,也就意味着如果存在i<j<k,且对于k来说j比i更优,那么之后的i再也不会比j优了。我们想找到的,就是当前节点最远能更新到哪个点。

不难发现,每个点能做出贡献的区间是一段连续的区间(可能为空)。我们可以用双向队列来找出每个点能作用的区间的左右端点lp和rp,具体方法:

1.枚举到当前点i时,先更新i的答案,然后将队首的lp改为i,如果队首lp>rp,则弹出队首。
2.如果队列不为空,且i对于n不如队尾优,说明i永远干不掉队尾,则不将i加入队列。
否则,如果i对于lp[队尾]比队尾更优,则弹出队尾。最后,i干掉队尾的位置就落在lp[队尾]和rp[队尾]之间,二分一下即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=500010;
int n,h,t;
int lp[maxn],rp[maxn],v[maxn],p[maxn],q[maxn];
int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
double solve(int a,int b)
{
	return v[a]-v[b]+sqrt(abs(b-a));
}
int main()
{
	n=rd();
	int i,l,r,mid;
	for(i=1;i<=n;i++)	v[i]=rd();
	for(h=1,t=0,i=1;i<=n;i++)
	{
		while(h<=t&&rp[q[h]]<i)	h++;
		if(h<=t)	lp[q[h]]=i,p[i]=max(p[i],(int)ceil(solve(q[h],i)));
		if(h>t||solve(i,n)>solve(q[t],n))
		{
			rp[i]=n;
			while(h<=t&&solve(i,lp[q[t]])>=solve(q[t],lp[q[t]]))	t--;
			if(h<=t)
			{
				l=lp[q[t]],r=rp[q[t]]+1;
				while(l<r)
				{
					mid=l+r>>1;
					if(solve(i,mid)<solve(q[t],mid))	l=mid+1;
					else	r=mid;
				}
				rp[q[t]]=l-1,lp[i]=l;
			}
			else	lp[i]=i+1;
			q[++t]=i;
		}
	}
	for(h=1,t=0,i=n;i>=1;i--)
	{
		while(h<=t&&lp[q[h]]>i)	h++;
		if(h<=t)	rp[q[h]]=i,p[i]=max(p[i],(int)ceil(solve(q[h],i)));
		if(h>t||solve(i,1)>solve(q[t],1))
		{
			lp[i]=1;
			while(h<=t&&solve(i,rp[q[t]])>=solve(q[t],rp[q[t]]))	t--;
			if(h<=t)
			{
				l=lp[q[t]],r=rp[q[t]];
				while(l<r)
				{
					mid=l+r>>1;
					if(solve(i,mid)<solve(q[t],mid))	r=mid;
					else	l=mid+1;
				}
				lp[q[t]]=r,rp[i]=r-1;
			}
			else	rp[i]=i-1;
			q[++t]=i;
		}
	}
	for(i=1;i<=n;i++)	printf("%d\n",p[i]);
	return 0;
}
时间: 2024-08-24 20:46:34

【BZOJ2216】[Poi2011]Lightning Conductor 决策单调性的相关文章

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'$,则有 $f[j]+\sqrt{i-j} \geqslant f[j']

bzoj2216: [Poi2011]Lightning Conductor(分治决策单调性优化)

每个pi要求 这个只需要正反DP(?)一次就行了,可以发现这个是有决策单调性的,用分治优化 #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn=500010,inf=1e9; int n; int a[

BZOJ2216 : [Poi2011]Lightning Conductor

$f[i]=\max(a[j]+\lceil\sqrt{|i-j|}\rceil)$, 拆开绝对值,考虑j<i,则决策具有单调性,j>i同理, 所以可以用分治$O(nlogn)$解决. #include<cstdio> #include<cmath> #define N 500010 int n,i,l,r,mid,a[N],b[N],f[N],g[N]; inline void read(int&a){char c;while(!(((c=getchar())

P3515 [POI2011]Lightning Conductor(决策单调性分治)

P3515 [POI2011]Lightning Conductor 式子可转化为:$p>=a_j-a_i+sqrt(i-j) (j<i)$ $j>i$的情况,把上式翻转即可得到 下面给一张图证明这是满足决策单调性的 把$a_j+sqrt(i-j)$表示在坐标系上 显然$sqrt(i-j)$的增长速度趋缓 曲线$a$被曲线$b$超过后是无法翻身的 对两个方向进行决策单调性分治,取$max$即可 #include<iostream> #include<cstdio>

[POI2011]Lightning Conductor

题面在这里 description 已知一个长度为\(n\)的序列\(a_1,a_2,...,a_n\). 对于每个\(1\le i\le n\),找到最小的非负整数\(p\), 满足对于任意的\(1\le j\le n\),\(a_j\le a_i+p-\sqrt{|i-j|}\) data range \[n\le 5\times 10^5,a_i\le 10^9\] solution 绝对值怎么办? 我们先从左到右\(DP\ j< i\)的部分(此时有\(|i-j|=i-j\)), 再右到

@bzoj - [email&#160;protected] [Poi2011]Lightning Conductor

目录 @[email protected] @[email protected] @part - [email protected] @part - [email protected] @part - [email protected] @accepted [email protected] @version - [email protected] @version - [email protected] @[email protected] @[email protected] 已知一个长度为

P3515 [POI2011]Lightning Conductor

首先进行一步转化 $a_j \leq a_i + q - sqrt(abs(i - j))$ $a_i + q \geq a_j + sqrt(abs(i-j))$ 即 $q = max (a_j + sqrt(abs(i-j))) - a_i $ 我们对$i \geq j 和 j > i$ 分类讨论, 其实解决一种情况后将序列翻转再做一遍即可 有一种O($n^2$)的dp暴力应该不难想到 那么我们现在思考如何以比较优秀的时间复杂度解决 这里涉及到决策单调性 简单的说, 对于i来说, 它的答案来

【bzoj2216】[Poi2011]Lightning Conductor 1D1D动态规划优化

Description 已知一个长度为n的序列a1,a2,…,an.对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p – sqrt(abs(i-j)) Input 第一行n,(1<=n<=500000)下面每行一个整数,其中第i行是ai.(0<=ai<=1000000000) Output n行,第i行表示对于i,得到的p Sample Input 6532424 Sample Output 235354 题解 http

决策单调性优化dp

决策单调性: 对于一些dp方程,经过一系列的猜想和证明,可以得出,所有取的最优解的转移点(即决策点)位置是单调递增的. 即:假设f[i]=min(f[j]+b[j]) (j<i) 并且,对于任意f[i]的决策点g[i],总有f[i+1]的决策点g[i+1]>=g[i](或者<=g[i]) 那么,这个方程就具备决策单调性. 这个有什么用吗? 不懂具体优化方法的话确实也没有什么用.可能还是n^2的.只不过范围可能少了一些. 经典入门例题: Description: [POI2011]Ligh