手动 assert 了一下,数据里是存在 sx=sy 的情况的,但是我把
double k(int x, int y){
return (double)(f[y] + g[y] - f[x] - g[x]) / (s[y] - s[x]);
}
改成
double k(int x, int y){
if(s[y] == s[x]) {return 1e18;}
return (double)(f[y] + g[y] - f[x] - g[x]) / (s[y] - s[x]);
}
之后就寄了,这是为啥捏?如果真的有横坐标相等他真的不会 RE 吗.
完整代码(AC的):
// “倘若某天我也悄无声息 死在了无人关注的角落里
// 希望某日你想起我不要难过哭泣 记得我说每次离别都是童话的开始”
// Problem: P2120 [ZJOI2007] 仓库建设
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2120
// Memory Limit: 128 MB
// Author: Fomalhaut
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define int long long
#define Maxn 1000007
using namespace std;
int a[Maxn], g[Maxn], s[Maxn], p[Maxn],
f[Maxn], x[Maxn], c[Maxn], q[Maxn];
int n;
double k(int x, int y){
return (double)(f[y] + g[y] - f[x] - g[x]) / (s[y] - s[x]);
}
signed main(){
cin >> n;
for(int i = 1; i <= n; i ++){
cin >> x[i] >> p[i] >> c[i];
s[i] = s[i - 1] + p[i];
g[i] = g[i - 1] + x[i] * p[i];
}
int l = 1;int r = 1;
for(int i = 1; i <= n; i ++){
while(l < r && k(q[l], q[l + 1]) < x[i]) l ++;
f[i] = f[q[l]] + x[i] * (s[i] - s[q[l]]) - g[i] + g[q[l]] + c[i];
while(l <= r && k(q[r - 1], q[r]) >= k(q[r], i)) r --;
q[++ r] = i;
//cout << f[i] << " ";
}
int qwq = n;
while(p[qwq] == 0) qwq --;
int ans = 1e18;
for(int i = qwq; i <= n; i ++) ans = min(ans, f[i]);
cout << ans;
}