[USACO08MAR]Land Acquisition
阿新 • • 發佈:2018-12-15
https per nod init play pla gis double !=
嘟嘟嘟
只要會決策單調性,這題就是練手的
首先按矩形長排序,這樣只用考慮寬了。
然後很容易搞出dp方程
\[dp[i] = min _ {j = 0} ^ {i - 1} (dp[j] + x[i] * max_{k = j + 1} ^ {i} y[k])\]
找max可以用st表達到\(O(1)\)。
打表發現決策單調。然後就是正常的優化了。
二分的時候需要註意當前隊列非空。要不然會像我一樣,不開氧氣AC,開了RE2個點。
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<stack> #include<queue> using namespace std; #define enter puts("") #define space putchar(‘ ‘) #define Mem(a, x) memset(a, x, sizeof(a)) #define rg register typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 5e4 + 5; inline ll read() { ll ans = 0; char ch = getchar(), last = ‘ ‘; while(!isdigit(ch)) last = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - ‘0‘, ch = getchar(); if(last == ‘-‘) ans = -ans; return ans; } inline void write(ll x) { if(x < 0) x = -x, putchar(‘-‘); if(x >= 10) write(x / 10); putchar(x % 10 + ‘0‘); } int n; ll dp[maxn]; struct Node { ll x, y; bool operator < (const Node& oth)const { return x < oth.x || (x == oth.x && y < oth.y); } }t[maxn]; struct Node2 { int pos, L, R; }q[maxn]; int l = 1, r = 0; ll Max[20][maxn], b[maxn]; void init() { for(int i = 1; i <= n; ++i) Max[0][i] = t[i].y; for(int j = 1; (1 << j) <= n; ++j) for(int i = 1; i + (1 << j) - 1 <= n; ++i) Max[j][i] = max(Max[j - 1][i], Max[j - 1][i + (1 << (j - 1))]); int x = 0; for(int i = 1; i <= n; ++i) { if((1 << (x + 1)) <= i) x++; b[i] = x; } } ll query(int L, int R) { int k = b[R - L + 1]; return max(Max[k][L], Max[k][R - (1 << k) + 1]); } ll w(int L, int R) { return query(L, R) * t[R].x; } int solve(int x, Node2 a) { int L = a.L, R = a.R; while(L <= R) { int mid = (L + R) >> 1; if(dp[x] + w(x + 1, mid) <= dp[a.pos] + w(a.pos + 1, mid)) { if(R != mid) R = mid; else {L = mid; break;} } else { if(L != mid + 1) L = mid + 1; else break; } } return L; } int main() { n = read(); for(int i = 1; i <= n; ++i) t[i].x = read(), t[i].y = read(); sort(t + 1, t + n + 1); init(); q[++r] = (Node2){0, 1, n}; for(int i = 1; i <= n; ++i) { while(q[l].R < i) l++; dp[i] = dp[q[l].pos] + w(q[l].pos + 1, i); q[l].L = i + 1; while(l <= r && dp[i] + w(i + 1, q[r].L) <= dp[q[r].pos] + w(q[r].pos + 1, q[r].L)) r--; int pos = i; if(l <= r) pos = solve(i, q[r]), q[r].R = pos - 1; if(pos <= n) q[++r] = (Node2){i, pos, n}; } write(dp[n]), enter; return 0; }
[USACO08MAR]Land Acquisition