标签:
题意:
要把
如果
题解:
先推期望公式。
设
然后观察得到从
然后设
转移:
发现这是个
当我们的
斜率优化可以看这里。
推出斜率公式为
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
double exc[N] = {0}, sum[N] = {0}, rev[N] = {0};
double t[N];
double dp[N][55];
inline double y(int x, int p){
return dp[x][p] - exc[x] + sum[x]*rev[x];
}
inline double g(int j, int k, int p){
return (y(j, p)-y(k, p))/(sum[j]-sum[k]);
}
inline double cal(int l, int i){
return exc[i]-exc[l]-(rev[i]-rev[l])*sum[l];
}
int q[N], top, tail;
inline void add(int i, int k){
while(top < tail-1 && g(i, q[tail-1], k) < g(q[tail-1], q[tail-2], k)) tail--;
q[tail++] = i;
}
inline int getmax(int i, int k){
while(top < tail-1 && g(q[top+1], q[top], k) < rev[i]) top++;
return q[top];
}
int main(){
int n, K;
scanf("%d%d", &n, &K);
for(int i = 1; i <= n; ++i) scanf("%lf", t+i);
for(int i = 1; i <= n; ++i){
sum[i] = sum[i-1] + t[i];
rev[i] = rev[i-1] + 1.0/t[i];
exc[i] = exc[i-1] + sum[i]/t[i];
}
for(int i = 1; i <= n; ++i) dp[i][1] = exc[i];
for(int k = 2; k <= K; ++k){
top = tail = 0;
q[tail++] = 0;
for(int i = 1; i <= n; ++i) add(i, k-1);
for(int i = 1; i <= n; ++i){
if(i >= k){
int l = getmax(i, k-1);
dp[i][k] = dp[l][k-1] + cal(l, i);
}
else dp[i][k] = 1e50; //不可能状态
}
}
printf("%.10f\n", dp[n][K]);
}
[斜率优化DP] codeforces 673E. Levels and Regions
标签:
原文地址:http://blog.csdn.net/kg20006/article/details/51346853