题意:给出一个序列,长度为n(n<=100000)均为正数。找出一段连续的区间,使得区间的平均值最大,满足区间的长度必须大于等于m。
思路:就这道题来说采用斜率优化和dp没什么关系了,主要就是数形结合,相当于斜率对于枚举的优化。参考了周源的论文,文章讲述的非常清晰。
首先i~j区间的平均值转换为sum(j)-sum(i-1)/j-(i-1),即转换为两点的斜率,于是问题转化为:平面上已知N+1个点,Pi(i, Si),0≤i≤N,求横向距离大于等于F的任意两点连线的最大斜率。接下来规定枚举方向,即考虑点i时只需考虑0<=j<=i-m的那些点(j构成考虑集合G)。接下里证明上凸点无用(具体见论文)。那么维护一个下凹的点集即可(思路类似于求凸包)。接着找最大斜率时再次用了这个思路,维护一个不减的下标即可。整个的均摊复杂度为O(n),非常精彩。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
#define INF 0x3fffffff
#define clr(s,t) memset(s,t,sizeof(s))
#define N 100005
int n,m;
int s[N],stack[N],top;
long long test(int a,int b,int c){
return (long long)(b-a)*(s[c]-s[a])-(long long)(c-a)*(s[b]-s[a]);
}
int main(){
int i,now,res;
scanf("%d %d",&n,&m);
s[0] = now = res = 0;
top = -1;
for(i = 1;i<=n;i++){
scanf("%d",&s[i]);

该博客介绍了如何解决寻找连续区间以获得最大平均值的问题,通过将问题转化为斜率优化,利用数形结合的思想,避免了动态规划。博主参考了周源的论文,提出当区间长度至少为m时,可以将平均值转化为两点斜率,然后优化枚举过程,只考虑下凹点集,最终实现O(n)的均摊复杂度解决方案。
最低0.47元/天 解锁文章
3700

被折叠的 条评论
为什么被折叠?



