题目链接:HDU2993
题目大意
给定一个正整数数列和
K
,定义
分析
1. 定义
S[i]
为前
i
项和,即求
2. 定义
dp[i]
为以
i
结束的合法子段,
3. 处理
dp[i]
之前把
i−k
推进
A
,并维护
优化
1. 考虑当前
dp[i]
在
A
中切点为
2. 此题卡读入,貌似连普通的读入优化也没用,只有用
fread
啦。
ps. 非常感谢
UOJ
上某
dalao
的
fread
模板,贸然取用,不要见怪啊。
UPD:终于把图给补了
上代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef double DB;
typedef long long LL;
const int N = 1e5 + 10;
int n, m;
LL sum[N];
namespace io //高级读入歪瓜
{
const int MAXBUF = 1 << 22;
char B[MAXBUF], *S = B, *T = B;
#define getc() (S == T && (T = (S = B) + fread(B, 1, MAXBUF, stdin), S == T) ? 0 : *S++)
template<class Type> inline Type read()
{
register Type aa = 0;
register bool bb = 0;
register char ch, *S = io::S, *T = io::T;
for(ch = getc(); (ch < '0' || ch > '9') && ch != '-'; ch = getc())
if (! ch) exit(0);
for(ch == '-' ? bb = 1 : aa = ch - '0', ch = getc(); '0' <= ch && ch <= '9'; ch = getc())
aa = aa * 10 + ch - '0';
io::S = S, io::T = T;
return bb ? -aa : aa;
}
int (*F)() = read<int>;
template<> inline double read()
{
register double aa, bb;
register char ch;
register char *S = io::S, *T = io::T;
while(ch=getc(),(ch<'0'||ch>'9'))
;aa=ch-'0';
while(ch=getc(),(ch>='0'&&ch<='9'))aa=aa*10+ch-'0';
if(ch=='.'){bb=1;while(ch=getc(),ch>='0'&&ch<='9')bb*=0.1,aa+=bb*(ch-'0');}
io::S = S, io::T = T;
return aa;
}
char buff[MAXBUF], *iter = buff;
template<class T>inline void P(register T x, register char ch = '\n')
{
static int stack[110];
register int O = 0;
register char *iter = io::iter;
if(!x)*iter++ = '0';
else
{
(x < 0) ? x = -x, *iter++ = '-' : 1;
for(; x; x /= 10)
stack[++O] = x % 10;
for(; O; *iter++ = '0' + stack[O--])
;
}
*iter++ = ch, io::iter = iter;
}
inline void putc(register char ch) {*iter++ = ch;}
inline void output() {fwrite(buff, 1, iter - buff, stdout), iter = buff;}
}
struct nodeQ {
int head, tail, val[N];
void pop_front() { head++; }
void pop_back() { tail--; }
void clear() { head = tail = 0; }
int size() { return tail - head; }
void push_back(int a) {val[tail++] = a; }
int back(int a) { return val[tail - a]; }
int front(int a) { return val[head + a - 1]; }
} Q;
#define Nu(a, b) (sum[a] - sum[b])
#define De(a, b) (a - b)
inline DB calcK(int a, int b) {
return (DB)Nu(a, b) / De(a, b);
}
inline bool judge(int a, int b, int c, int d) {
return Nu(a, b) * De(c, d) <= Nu(c, d) * De(a, b);
}
int main() {
int (*F)() = io::read<int>;
while (1) {
n = F(); m = F();
DB maxn = 0;
Q.clear();
for (int i = 1; i <= n; i++)
sum[i] = F() + sum[i - 1];
for (int i = m; i <= n; i++) { //斜率优化,维护解集下凸且第一个点为合法最优解
int tmp = i - m;
while (Q.size() >= 2 && judge(tmp, Q.back(1), Q.back(1), Q.back(2)))
Q.pop_back();
Q.push_back(tmp);
while (Q.size() >= 2 && judge(i, Q.front(1), i, Q.front(2)))
Q.pop_front();
maxn = max(maxn, calcK(i, Q.front(1)));
}
printf("%.2lf\n", maxn);
}
return 0;
}
以上