http://acm.hdu.edu.cn/showproblem.php?pid=2993
题意:给你一段长度为n的数列, 求其长度不小于 K 的平均值最大的子串。
解析参考:http://blog.ac521.org/?p=565
大意是先将问题转化为求斜率的问题,然后将朴素的N^2的算法用下凸曲线维护(要推导一些性质),降为2N的复杂度
数形结合
#include <cstdio> #include <iostream> #include <fstream> #include <cstring> using namespace std; int N,K; int sum[100010]; struct point { double x,y; }; void read(int & a) { char ch; while (ch = getchar(),ch < '0' || ch > '9'); a = ch - '0'; while (ch = getchar(),ch >= '0' && ch <= '9') a = a*10 + ch - '0'; } double solve() { double maxx = 0; static point s[100010]; int head = 1,tail = 0; for (int j = K; j <= N; j++) { int k = j - K; while (tail-1 >= head && (s[tail].x - s[tail-1].x)*(sum[k] - s[tail].y) - (s[tail].y - s[tail-1].y)*(k - s[tail].x)<0)//if (tail-1 >= head) { tail --; } s[++tail].x = k; s[tail].y = sum[k]; while (head+1 <= tail && (sum[j] - s[head].y)/(j - s[head].x) < (sum[j] - s[head+1].y)/(j - s[head+1].x)) head++; double temp = (double)(sum[j] - s[head].y)/(j - s[head].x); //cout<<temp<<endl; if (temp > maxx) maxx = temp; } return maxx; } int main() { freopen("test.txt","r",stdin); while(~scanf("%d%d",&N,&K)) { sum[0] = 0; for (int i = 1; i <= N; i++) { read(sum[i]); sum[i] += sum[i-1]; } printf("%.2lf\n",solve()); } return 0; }