HDU 2993 MAX Average Problem(斜率优化DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993
题目大意:给定一个长度为n(最长为10^5)的正整数序列,求出连续的最短为k的子序列平均值的最大值。
Sample Input
10 6
6 4 2 10 3 8 5 9 4 1
Sample Output
6.50
分析:斜率优化DP,要认真看
代码如下:
1 # include<iostream> 2 # include<cstdio> 3 # include<cstring> 4 # include<algorithm> 5 6 using namespace std; 7 8 const int maxn = 100010; 9 double a[maxn], sum[maxn]; 10 int n,k; 11 int q[maxn],head,tail; 12 13 //读入优化,否则超时 14 int GetInt() 15 { 16 char ch=getchar(); 17 while(ch<'0' || ch>'9') 18 ch = getchar(); 19 int num = 0; 20 while(ch >= '0' && ch<='9') 21 { 22 num = num*10 + ch - '0'; 23 ch = getchar(); 24 } 25 return num; 26 } 27 28 void DP() 29 { 30 head = tail =0; 31 double ans = -1; 32 for(int i=k; i<=n; i++) 33 { 34 int j = i-k; 35 //维护下凸 36 while(tail - head >=2) 37 { 38 double x1 = j - q[tail-1]; 39 double y1 = sum[j] - sum[q[tail-1]]; 40 double x2 = q[tail-1] - q[tail-2]; 41 double y2 = sum[q[tail-1]] - sum[q[tail-2]]; 42 if(x1 * y2 - y1 *x2 >= 0) 43 tail--; 44 else 45 break; 46 } 47 q[tail++] = j; 48 //寻找最优解并删除无用元素 49 while(tail - head >=2) 50 { 51 double x1 = i - q[head]; 52 double y1 = sum[i] - sum[q[head]]; 53 double x2 = i - q[head+1]; 54 double y2 = sum[i] - sum[q[head+1]]; 55 if(x1*y2 - y1*x2 >= 0) 56 head ++; 57 else 58 break; 59 } 60 double tmp = (sum[i] - sum[q[head]])/(i-q[head]); 61 ans = max(ans, tmp); 62 } 63 printf("%.2lf\n",ans); 64 } 65 66 int main() 67 { 68 //freopen("in.txt","r",stdin); 69 while(scanf("%d%d",&n,&k)!=EOF) 70 { 71 sum[0] = 0; 72 for(int i=1; i<=n; i++) 73 { 74 a[i] = GetInt(); 75 sum[i] = sum[i-1] + a[i]; 76 } 77 DP(); 78 } 79 return 0; 80 }
把每一件简单的事情做好,就是不简单;把每一件平凡的事情做好,就是不平凡!相信自己,创造奇迹~~