您的位置:首页 > 其它

SCU2016-01 I题 二分 + 斜率优化dp

2016-09-04 16:07 393 查看
分析

套路题。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define pr(x) cout << #x << ": " << x << "  "
#define pl(x) cout << #x << ": " << x << endl;
typedef long long ll;

const int N = 2e5+5;
ll val
, sum
= {0}, p
= {0};
int q
, top, tail;

inline ll y(int x){ return p[x] - x*sum[x]; }
double g(int j, int k){
double dy = y(j) - y(k);
double dx = j - k;
return dy/dx;
}

inline ll getans(int i, int j){
return p[i] - p[j] - j*(sum[i] - sum[j]);
}

int solve(ll x){
int l = top, r = tail-1, mid, res = l;
while(l <= r){ //根据斜率二分求最优点
mid = (l+r) >> 1;
if(g(q[mid], q[mid-1]) < -x) l = mid+1, res = mid;
else r = mid-1;
}
return q[res];
}

int main(){
#ifdef LOCAL
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
int T =1 ;
// scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%lld", val+i);
sum[i] = sum[i-1] + val[i];
p[i] = p[i-1] + i*val[i];
}
top = tail = 0;
q[tail++] = 0;
ll ans = 0;
for(int i = 1; i <= n; ++i){
int j = solve(sum[i]); //对于固定的i,二分求最优点
ans = max(ans, getans(i,j)); //更新答案
while(top < tail-1 && g(i, q[tail-1]) < g(q[tail-1], q[tail-2])) tail--;//满足了g(i,j)<g(j,k)
q[tail++] = i;
}
printf("%lld\n", ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: