题解 P3299 【[SDOI2013]保护出题人】
ModestCoder_ · · 题解
这并不是一道dp
对于每个
可以斜率优化,因为答案的表达式可以看成
发现对于每个
所以对于点
把每一个
Code:
#include <bits/stdc++.h>
#define maxn 100010
#define int long long
using namespace std;
struct data{
int x, y;
}stk[maxn];
int n, D, sum[maxn], top;
double Ans;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
double slope(data x, data y){ return 1.0 * (x.y - y.y) / (x.x - y.x); }
signed main(){
n = read(), D = read();
stk[0] = (data){0, 0};
for (int i = 1; i <= n; ++i){
int x = read(), y = read(); sum[i] = sum[i - 1] + x;
data tmp = {i * D, sum[i - 1]};
while (top && slope(stk[top - 1], stk[top]) > slope(stk[top], tmp)) --top;
stk[++top] = tmp;
tmp = (data){y + i * D, sum[i]};
int l = 1, r = top, ans = 0;
while (l <= r){
int mid = (l + r) >> 1;
if (slope(stk[mid], tmp) > slope(stk[mid - 1], tmp)) ans = mid, l = mid + 1; else r = mid - 1;
}
Ans += slope(stk[ans], tmp);
}
printf("%.0f\n", Ans);
return 0;
}