HDU 2993 - MAX Average Problem - [斜率DP]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993
Input
There multiple test cases in the input, each test case contains two lines.
The first line has two integers, N and k (k<=N<=10^5).
The second line has N integers, a1, a2 ... an. All numbers are ranged in [1, 2000].
Output
For every test case, output one single line contains a real number, which is mentioned in the description, accurate to 0.01.
Sample Input
10 6
6 4 2 10 3 8 5 9 4 1
Sample Output
6.50
题意:
定义ave(i,j) = ( a[i] + a[i+1] + … + a[j-1] + a[j] ) / ( j - i + 1 ),现给定一个整数k且规定j - i + 1 ≥ k,求max(ave(i,j)).
题意:
我们设sum[0~N]是a[1~N]的前n项和,且sum[0]=0,那么就有:
不妨把ave(i,j)看做是点i-1到点j的斜率;
我们设dp[j]代表max(ave(i,j)),j-i+1≥k;
换句话说,在规定最少要连续取到k个值的前提下,a[1~j]中必有一个连续子序列,它以a[j]为结尾,且是所有a[1~j]的连续子序列中平均值最大的,把这个平均值记为dp[j]。
那么题目的最终答案就是max( dp[k] , dp[k+1] , … , dp[N] )。
问题相应可以转化为:
现有0~N这N+1个平面坐标系内的点,每个点P[i]的坐标为(i,sum[i]),0≤i≤N,要求任意横向距离差不小于k的两个点间,最大的斜率为多少。
现在对求斜率有方向化,规定对i<j,只检查从点P[j]到点P[i]的连线的斜率,不检查从P[i]到P[j]的连线。
那么,对于一个点P[j],定义其检查集合为:
G[j] = {P[i] , 0 ≤ i ≤ j - k }
显然,j取值应当从k到n;当j<k时,G[j]为空集。
那么,dp[j]定义相应可变为:G[j]中任选一个点P[i],它与P[j]的连线斜率最大,这个斜率记为dp[j]。
那么,在朴素的思想中,我们若要求一个dp[t],必然要枚举检查G[t]中所有的点;
但是我们通过观察,可以发现如下性质:
若G[t]中存在三个点P[i],P[j],P[k],i<j<k,并且P[j]在直线P[i]P[k]的上方,那么必然可以淘汰P[j]。
证明:
设g(P1,P2)代表直线P1P2的斜率,则:
若g(P[j],P[t]) ≥ g(P[i],P[t]),那么P[t]必然落在区域②中;
若g(P[j],P[t]) ≥ g(P[k],P[t]),那么P[t]必然落在区域③中;
但是显然区域②和③显然没有符合条件(t>k)的相交区域,故不可能同时满足g(P[j],P[t]) ≥ g(P[i],P[t])和g(P[j],P[t]) ≥ g(P[k],P[t]);
也就是说要么g(P[j],P[t]) < g(P[i],P[t]),要么g(P[j],P[t]) < g(P[k],P[t]),显然j总归不如i或者k中至少一个优,即证明了j必然淘汰。
这样一来,由于我们去掉了所有上凸的点,就维护了一个下凸的折线图形:
显然当P[t]切到这个折线时,斜率最大,即为dp[t]。
那么相应的我们可以建立一个存储点的队列,维护下凸图形,有以下的算法过程:
首先枚举 j = k ~ N,按以下两步尝试计算dp[j]:
①首先令点i = j - k,尝试将点i入队:
若队列尾部存在点a和b,且g(a,b) ≥ g(b,i),则删去元素b;
(原因:若G[t]中存在三个点P[i],P[j],P[k],i<j<k,并且P[j]在直线P[i]P[k]的上方,那么必然可以淘汰P[j]。)
不断重复上述操作,直到队列内元素少于2,或者g(a,b) < g(b,i);然后将点i入队。
②现在,所有点P[0]到点P[j - k]都曾经进入过队列了,那么此时可以通过队列的性质计算dp[j]:
若队列头部存在点a和b,且g(a,b) ≤ ave(b,j),则将元素a删去;
反复上述操作,直到队列元素少于2,或者ave(a,b) > ave(b,j);然后再选取队头元素得到dp[j]=g(q[head],j)。
这样做的原因上面讲过,不再赘述。
(删去的这些队列头部的元素,不难发现,在求dp[j]时它们不能成为最优解,在往后的dp[j+1],dp[j+2]……中依然不可能成为最优解,所以可以直接删去。)
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+; int n,k,sum[maxn];
int q[maxn],head,tail; //输入外挂
int tot;
const int BUF=;
char Buf[BUF],*buf=Buf;
inline void read(int &a)
{
for(a=;*buf<;buf++);
while(*buf>) a=a*+*buf++-;
} double inline g(int i,int j){return (double(sum[j]-sum[i]))/(double(j-i));} int main()
{
tot=fread(Buf,,BUF,stdin); while()
{
if(buf-Buf+>=tot) break; read(n),read(k);
sum[]=;
for(int i=;i<=n;i++)
{
read(sum[i]);
sum[i]+=sum[i-];
} head=tail=;
double ans=;
for(int j=k;j<=n;j++)
{
int i=j-k; while( head+<tail && g(q[tail-],q[tail-])>=g(q[tail-],i) ) tail--;
q[tail++]=i; while( head+<tail && g(q[head],q[head+])<=g(q[head+],j) ) head++;
ans=max(ans,g(q[head],j));
}
printf("%.2f\n",ans);
}
}
注意点:
①要使用输入加速外挂,而且不能是一般的getchar版的,要是fread版的加速挂。
②结合前一道题目http://www.cnblogs.com/dilthey/p/8745843.html来看,斜率DP一定要讲究理论基础,理论严密基础扎实,写出来的代码才不会WA。
HDU 2993 - MAX Average Problem - [斜率DP]的更多相关文章
- hdu 2993 MAX Average Problem(斜率DP入门题)
题目链接:hdu 2993 MAX Average Problem 题意: 给一个长度为 n 的序列,找出长度 >= k 的平均值最大的连续子序列. 题解: 这题是论文的原题,请参照2004集训 ...
- HDU 2993 MAX Average Problem dp斜率优化
MAX Average Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- 数据结构:HDU 2993 MAX Average Problem
MAX Average Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- HDU 2993 MAX Average Problem(斜率DP经典+输入输出外挂)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 题目大意:给出n,k,给定一个长度为n的序列,从其中找连续的长度大于等于k的子序列使得子序列中的 ...
- HDU 2993 MAX Average Problem(斜率优化DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 题目大意:给定一个长度为n(最长为10^5)的正整数序列,求出连续的最短为k的子序列平均值的最大 ...
- HDU 2993 MAX Average Problem(斜率优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 Problem Description Consider a simple sequence w ...
- MAX Average Problem(斜率优化dp)
MAX Average Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- BNUOJ 3958 MAX Average Problem
MAX Average Problem Time Limit: 3000ms Memory Limit: 65536KB 64-bit integer IO format: %lld Jav ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
随机推荐
- 时间戳Id
ID:格式据1970.1.1毫秒数 1535091029740 13位 问题:高并发,分布式明显会有问题,网上有雪花算法,但是位数跟我需要的不一样,暂时不考虑,以后研究再用. 参考: https:/ ...
- Dubbo -- 系统学习 笔记 -- 示例 -- 多注册中心
Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 多注册中心 可以自行扩展注册中心,参见:注册中心扩展 (1) 多注册中心注册 比如 ...
- 8 -- 深入使用Spring -- 2... Spring的“零配置”支持
8.2 Spring的“零配置”支持 Spring支持使用Annotation来代替XML配置文件.
- 存储过程中SELECT INTO的使用
在MySQL存储过程中使用SELECT …INTO语句为变量赋值: 用来将查询返回的一行的各个列值保存到局部变量中. 要求: 查询的结果集中只能有1行. SELECT col_name[,...] I ...
- vs 2010中如何检查内存泄露
首先,在文件头添加下面的内容: #ifdef _DEBUG#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)#else# ...
- Bypassing PatchGuard on Windows x64
[说明] 1. 本文是意译,加之本人英文水平有限.windows底层技术属菜鸟级别,本文与原文存在一定误差,请多包涵. 2. 由于内容较多,从word拷贝过来排版就乱了.故你也可以下载附件. 3. ...
- EGit系列第一篇——创建本地仓库
首先,用Eclipse创建一个项目,然后右键项目Team\Share Preject... 然后出来Share Preject对话框,选择git 点击下一步配置Git仓库,通常在项目本地目录创建仓库, ...
- WP8.1学习系列(第七章)——应用选项卡Pivot交互UX
“应用选项卡”模式用于用户经常在中间导航的多个 UI 页面.如果你的应用基于单个主题(例如,电影.棒球等),该模式尤其有用.每页都将为用户显示与该应用呈现的整体数据相关的一些内容.“应用选项卡”模式可 ...
- 使用TELNET手工操作 IMAP 查看邮件
http://www.cnblogs.com/CrazyWill/archive/2006/08/12/474884.html IMAP 协议收信与POP收信有很大的不同,最明显的一点就是发送的每条命 ...
- Mysql 的事务隔离级别
SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的.低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销.Read Uncommitted(读取 ...