ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

T1 P3515 [POI2011]Lightning Conductor

2021-02-24 22:03:58  阅读:187  来源: 互联网

标签:int POI2011 sol Lightning tail rg include dp P3515


思路:

首先考虑n^2暴力枚举:ans[i]=max(a[j]+sqrt(|i-j|)-a[i] (1<=j<=n)

把绝对值拆开:
ans[i]=max(a[j]+sqrt(i-j))-a[i] (1<=j<=i)

ans[i]=max(a[j]+sqrt(j-i))-a[i] (i<j<=n)

发现这个式子具有对称性,也就是说对于一个点i,他的最优决策j有可能是在j的左边,也有可能是在j的右边,这是绝对值带来的影响,所以我们从前往后扫一遍,从后往前扫一便,就可以消除abs的影响

对于函数y=sqrt(x),他的增长速度是越来越慢的,我们先考虑从前往后的情况,如果决策点j不变的情况下,i不断增大,那么sqrt(i-j)的增长速度就是不断减小的

我们的dp方程求得是最大值

如果i不断增大,决策点j产生的dp值的增幅不断减小(但是仍在增长),那就有可能存在一个决策点,虽然他之前的贡献比较小,但是增幅大,所以k有可能取代j形成dp[i]的最优解

那么对于每一个决策点j,就可能形成最优解的范围应当是一段区间

这样,我们的一个dp优化思路就是开一个单调队列,保存三元组(p,l,r),表示决策p的管辖范围是(l,r)内,(所有元素的l ~ r构成1 ~ n)我们枚举到一个i的时候,队头的l++,如果管辖范围为空(i不在head的管辖范围之内),那么就可以删去

此时对于dp[i]而言,队头存储的就是最优决策点

如果此时对于dp[n]而言,决策点p并没有i优,那么我们就是要在队尾加入决策点i

i的管辖范围就是i~n

因为增长速度是存在单调性的,也就是说如果在某一段时间p没有i优,那么p就一直没有i优,所以我们可以二分临界

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define il inline
#define rg register
#define ll long long
#define N 540000
#define inf 2147483647
#define ll_inf 9223372036854775807
using namespace std;
int n,num[N];
double F[N],G[N];
struct T{
	int p,l,r;
}Q[N];
il void re(rg int &x);
double sol(rg int i,rg int j){
	return (double)num[j]+sqrt((double)(1.0*abs(i-j)));
}
int find(rg int le,rg int ri,rg int p,rg int i){
	rg int ans=-1;
	while(le<=ri){
		rg int mid=((le+ri)>>1);
		if(sol(mid,p)>sol(mid,i))le=mid+1;
		else ri=mid-1,ans=mid;
	}
	return ans;
}
int main(){
	freopen("s.in","r",stdin);
	re(n);
	for(rg int i=1;i<=n;++i)
		re(num[i]);
	//dp[i]=max(num[j]-num[i]+sqrt(abs(i-j)));
    //需要求出最优的解
	rg int tail=0,head=1;
	for(rg int i=1;i<=n;++i){
		Q[head].l++;
		if(head<=tail&&Q[head].r<Q[head].l)head++;
		if(head>tail||sol(n,i)>sol(n,Q[tail].p)){
			while(head<=tail&&sol(Q[tail].l,Q[tail].p)<sol(Q[tail].l,i))tail--;
			if(head>tail)
				Q[++tail].p=i,Q[tail].l=i,Q[tail].r=n;
			else{
				rg int temp=find(Q[tail].l,Q[tail].r,Q[tail].p,i);
				Q[tail].r=temp-1;
				Q[++tail].p=i,Q[tail].l=temp,Q[tail].r=n;
			}
		}
		F[i]=sol(i,Q[head].p)-num[i];
	}
	reverse(num+1,num+n+1);
	tail=0,head=1;
	for(rg int i=1;i<=n;++i){
		Q[head].l++;
		if(head<=tail&&Q[head].r<Q[head].l)head++;
		if(head>tail||sol(n,i)>sol(n,Q[tail].p)){
			while(head<=tail&&sol(Q[tail].l,Q[tail].p)<sol(Q[tail].l,i))tail--;
			if(head>tail)
				Q[++tail].p=i,Q[tail].l=i,Q[tail].r=n;
			else{
				rg int temp=find(Q[tail].l,Q[tail].r,Q[tail].p,i);
				Q[tail].r=temp-1;
				Q[++tail].p=i,Q[tail].l=temp,Q[tail].r=n;
			}
		}
		G[i]=sol(i,Q[head].p)-num[i];
	}
	reverse(G+1,G+n+1);
	for(rg int i=1;i<=n;++i)
		printf("%d\n",max(0,(int)ceil(max(F[i],G[i]))));
    return 0;
}
il void re(rg int &x){
    rg int res=0;rg int w=1;char c=getchar();
    while((c<'0'||c>'9')&&c!='-')c=getchar();
    if(c=='-')w=-1,c=getchar();
    while(c>='0'&&c<='9')res=(res<<3)+(res<<1)+c-'0',c=getchar();
    x=w*res;
}

标签:int,POI2011,sol,Lightning,tail,rg,include,dp,P3515
来源: https://www.cnblogs.com/yxr001002/p/14444050.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有