最近复习到斜率优化,觉得之前写的 (dp[que[tail]] - dp[que[tail - 1]]) * (s_f[i] - s_f[que[tail]]) >= (dp[i] - dp[que[tail]]) * (s_f[que[tail]] - s_f[que[tail - 1]]) 这种比较斜率的方式太恶心了,所以换成了直接比较斜率:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 3e5 + 9;
const double eps = 1e-6;
int n,s;
int s_t[N],s_f[N];
int dp[N];
double slope(int p1,int p2){
return (double)(dp[p1] - dp[p2]) / (double)(s_f[p1] - s_f[p2]);
}
int que[N];
int head = 1,tail;
int bnsearch(int l,int r,int k){
int mid = 0;
while(l < r){
mid = (l + r) >> 1;
if(slope(que[mid + 1],que[mid]) <= k - eps)
l = mid + 1;
else
r = mid;
}
return que[l];
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> s;
for(int i = 1;i <= n;i++) {
cin >> s_t[i] >> s_f[i];
s_t[i] += s_t[i - 1];
s_f[i] += s_f[i - 1];
}
que[++tail] = 0;
for(int i = 1;i <= n;i++){
int j = bnsearch(head,tail,s + s_t[i]);
dp[i] = dp[j] + s * (s_f[n] - s_f[j]) + s_t[i] * (s_f[i] - s_f[j]);
while(head < tail && slope(que[tail],que[tail - 1]) >= slope(i,que[tail]) + eps)
tail--;
que[++tail] = i;
}
cout << dp[n];
return 0;
}
我用这种方法通过了 CF311B,但是无法通过本题(80 pts)。
所以这种写法是存在精度问题,还是说这种写法不适用于二分?