C - Kalila and Dimna in the Logging Industry
很容易能得到状态转移方程 dp[ i ] = min( dp[ j ] + b[ j ] * a[ i ] ), 然后斜率优化一下。
一直以为炸精度了, 忽然发现手贱把while 写成了if 。。。。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 4e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; int n, que[N], head, rear; LL a[N], b[N], dp[N]; double calc(int k, int j) { return 1.0 * (dp[j] - dp[k]) * (b[k] - b[j]); } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%lld", &a[i]); for(int i = 1; i <= n; i++) scanf("%lld", &b[i]); dp[1] = 0; head = 1, rear = 0; que[++rear] = 1; for(int i = 2; i <= n; i++) { while(rear - head + 1 >= 2 && calc(que[head], que[head + 1]) < a[i]) head++; dp[i] = dp[que[head]] + b[que[head]] * a[i]; while(rear - head + 1 >= 2 && calc(que[rear-1], que[rear]) >= calc(que[rear], i)) rear--; que[++rear] = i; } printf("%lld\n", dp[n]); return 0; } /* */