BZOJ2216[Poi2011]Lightning Conductor 决策单调性
Posted CQzhangyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
5
3
2
4
2
4
Sample Output
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; }
以上是关于BZOJ2216[Poi2011]Lightning Conductor 决策单调性的主要内容,如果未能解决你的问题,请参考以下文章
bzoj2216: [Poi2011]Lightning Conductor(分治决策单调性优化)
bzoj 2216 [Poi2011]Lightning Conductor 决策单调性+dp
bzoj2216[Poi2011]Lightning Conductor 1D1D动态规划优化