小A与最大子段和 斜率优化 + 二分 + 细节

Code:

#include <bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin)
#define x(i) (1.0000*i)
#define y(i) (1.0000*s2[i]*i-1.00000*s1[i])
#define maxn 300000
#define ll long long
#define ldb double
using namespace std;
int tail,head,n;
int q[maxn];
ll s1[maxn],s2[maxn],f[maxn];
ldb slope(int i,int j) { return (ldb)(1.0*y(i)-y(j))/(ldb)(1.0*x(i)-x(j));    }
int main()
{
	int i,j;
	ll ans=-1e18;
	// setIO("input");
	scanf("%d",&n);
	for(i=1;i<=n;++i)
	{
		scanf("%lld",&s2[i]);
		s1[i]=s1[i-1]+s2[i]*i;
		s2[i]+=s2[i-1];
	}
	head=tail=1;
	for(i=1;i<=n;++i)
	{
		int l=head,r=tail,re=0,mid=0;
		while(l<=r)
		{
			mid=(l+r)>>1;
			if(mid==tail) { re=tail;  break;    }
			if(slope(q[mid],q[mid+1])<=s2[i]) re=mid,r=mid-1;
			else l=mid+1;
		}
		f[i]=s1[i]-s1[q[re]]-(s2[i]-s2[q[re]])*q[re];
		ans=max(ans,f[i]);
		while(head<tail&&slope(i,q[head-1])>slope(q[head],q[head-1])) --tail;
		q[++tail]=i;
	}
	printf("%lld\n",ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/11143029.html

时间: 2024-10-11 08:23:38

小A与最大子段和 斜率优化 + 二分 + 细节的相关文章

BZOJ3437:小P的牧场(DP+斜率优化)

小P的牧场[题目描述]背景:小P 是个特么喜欢玩MC 的孩纸...小P 在MC 里有n 个牧场,自西向东呈一字形排列(自西向东用1…n 编号),于是他就烦恼了:为了控制这n 个牧场,他需要在某些牧场上面建立控制站,每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场(它西边第一个控制站所在的牧场不被控制)(如果它西边不存在控制站,那么它控制西边所有的牧场),每个牧场被控制都需要一定的花费(毕竟在控制站到牧场间修建道路是需要资源的嘛~),而且该花费等于

任务安排 HYSBZ - 2726 (斜率优化 + 二分)

机器上有N个需要处理的任务,它们构成了一个序列.这些任务被标号为1到N,因此序列的排列为1,2,3...N.这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti.在每批任务开始前,机器需要启动时间S,而完成这批任务所需的时间是各个任务需要时间的总和.注意,同一批任务将在同一时刻完成.每个任务的费用是它的完成时刻乘以一个费用系数Fi.请确定一个分组方案,使得总费用最小. Input 第一行两个整数,N,S. 接下来N行每行两个整数,T

bzoj3672/luogu2305 购票 (运用点分治思想的树上cdq分治+斜率优化dp)

我们都做过一道题(?)货币兑换,是用cdq分治来解决不单调的斜率优化 现在它放到了树上.. 总之先写下来dp方程,$f[i]=min\{f[j]+(dis[i]-dis[j])*p[i]+q[i]\} ,j是i的祖先,dis[i]-dis[j]<=l[i]$ ,其中dis[i]表示1号点到i号点的距离 可以很明显的看出斜率优化,但我们要放到树上做 于是就运用点分治的思想来找重心(正如普通的cdq是找重点一样) 步骤是这样的: 1.对于根为x的一个子树,我们先找到它的重心rt 2.把rt的子树刨掉

BZOJ3437 小P的牧场(斜率优化dp)

题目link:http://www.lydsy.com/JudgeOnline/problem.php?id=3437; 略略读一下题,发现这题是一道dp 有一些牧场: 1 2 3 4 5 6 7 8 9 10 其中编号大的可以管住编号小的. a[i]表示建站费用 b[i]表示养殖奶牛数目 dp方程大概就出来了 f[i]=min(f[j]+cost(j+1,i)) (0<j<i); 可是有些问题需要O(1)计算cost(j+1,i); 怎么办呢? 于是我想了一个很不清真的计算方法 开了两个数组

bzoj3437小P的牧场 斜率优化dp

3437: 小P的牧场 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1542  Solved: 849[Submit][Status][Discuss] Description 小P在MC里有n个牧场,自西向东呈一字形排列(自西向东用1…n编号),于是他就烦恼了:为了控制这n个牧场,他需要在某些牧场上面建立控制站,每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场(它西边第一个控制站所在的牧场不被

【BZOJ3437】小P的牧场 斜率优化 动态规划

呃,老规矩,方程.转化神马的都在代码注释里面. 不会斜率优化的移步这篇:http://blog.csdn.net/vmurder/article/details/41648159 没事闲的想看点经验的来"前一篇"http://blog.csdn.net/vmurder/article/details/41682901 代码: #include <cstdio> #include <cstring> #include <iostream> #inclu

BZOJ 3437 小P的牧场 斜率优化DP

题目大意:有些按照一字排列的牧场,每一个牧场有一个费用和放牧数量.现在要在一些牧场上建造控制站,目的是控制所有的牧场,建立控制站的基础费用就是每个牧场的费用,然后每一个牧场需要付这个牧场的放养数量*它与右边相邻的控制站的距离.求最小的费用. 思路:直接弄有些不好弄,需要两个前缀和来进行差分. sum[i] = Σsrc[i] _sum[i] = Σsrc[i]*i 然后DP方程就是f[i] = f[j] + (sum[i] - sum[j]) * i - _sum[i] + _sum[j] 简单

bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜.所以,一段路必须在同一天中走完. Pine希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小. 帮助Pine求出最小方差是多少. 设方差是v,可以证明,v×m^2是一个整数.为了避免精度误差,输出结果时输出v×m^2. In

斜率优化技巧——换个角度思考

[bzoj3437]小P的牧场 试题描述 背景 小P是个特么喜欢玩MC的孩纸... 描述 小P在MC里有n个牧场,自西向东呈一字形排列(自西向东用1…n编号),于是他就烦恼了:为了控制这n个牧场,他需要在某些牧场上面建立控制站,每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场(它西边第一个控制站所在的牧场不被控制)(如果它西边不存在控制站,那么它控制西边所有的牧场),每个牧场被控制都需要一定的花费(毕竟在控制站到牧场间修建道路是需要资源的嘛~),