bzoj 2216 [Poi2011]Lightning Conductor 決策單調性+dp
阿新 • • 發佈:2018-08-15
pre inline 假設 int efi 當前 www. 記錄 sin 優,那麽直接把\(p\)刪掉
題面
題目傳送門
解法
決策單調性比較經典的題吧
題目就是要對於每一個\(i\)求\(f_i=max(a_j-a_i+\sqrt{|i-j|}))\)
可以發現,\(\sqrt n\)的增長速度比較慢,所以滿足決策單調性
決策單調性是指,如果決策\(j\)對於\(i\)已經不是最優的了,那麽在後面也一定不是最優的
我們可以對於每一個\(i\)記錄它是由哪一個決策\(j\)轉移而來的
可以發現,只要出現在決策表中的數一定構成若幹段區間
那麽,我們只要開一個隊列,記錄每一個決策的轉移區間即可
假設當前隊尾為決策\(p\),對應最優區間為\([l,r]\)
如果在\(l\)這個位置發現\(i\)比\(p\)
如果在\(r\)這個位置發現\(i\)沒有\(p\)優,那麽就可以不用管了
否則,二分中間的斷點,更新區間
用一個雙端隊列來實現這個過程
註意:本題需要考慮上取整等操作,所以在轉移的時候不要把double轉成int,否則會影響結果
時間復雜度:\(O(n\ log\ n)\)
代碼
#include <bits/stdc++.h> #define N 500010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x, y);} template <typename node> void chkmin(node &x, node y) {x = min(x, y);} template <typename node> void read(node &x) { x = 0; int f = 1; char c = getchar(); while (!isdigit(c)) {if (c == ‘-‘) f = -1; c = getchar();} while (isdigit(c)) x = x * 10 + c - ‘0‘, c = getchar(); x *= f; } struct Node { int p, l, r; } q[N]; int a[N], f[N], g[N]; double calc(int x, int y) { return (double)a[y] + sqrt(abs(y - x)); } int solve(int pos, int L, int R, int i) { int l = L, r = R, ans = -1; while (l <= r) { int mid = (l + r) >> 1; if (calc(mid, pos) <= calc(mid, i)) r = mid - 1, ans = mid; else l = mid + 1; } return ans; } int main() { int n; read(n); for (int i = 1; i <= n; i++) read(a[i]); int h = 1, t = 0; for (int i = 1; i <= n; i++) { q[h].l++; while (h <= t && q[h].r < q[h].l) h++; if (h > t || calc(n, q[t].p) < calc(n, i)) { while (h <= t && calc(q[t].l, q[t].p) < calc(q[t].l, i)) t--; if (h <= t) { int x = solve(q[t].p, q[t].l, q[t].r, i); q[t].r = x - 1; q[++t] = (Node) {i, x, n}; } else q[++t] = (Node) {i, i, n}; } f[i] = ceil(calc(i, q[h].p) - a[i]); } reverse(a + 1, a + n + 1); memset(q, 0, sizeof(q)); h = 1, t = 0; for (int i = 1; i <= n; i++) { q[h].l++; while (h <= t && q[h].r < q[h].l) h++; if (h > t || calc(n, q[t].p) < calc(n, i)) { while (h <= t && calc(q[t].l, q[t].p) < calc(q[t].l, i)) t--; if (h <= t) { int x = solve(q[t].p, q[t].l, q[t].r, i); q[t].r = x - 1; q[++t] = (Node) {i, x, n}; } else q[++t] = (Node) {i, i, n}; } g[i] = ceil(calc(i, q[h].p) - a[i]); } for (int i = 1; i <= n; i++) cout << max(0, max(f[i], g[n - i + 1])) << "\n"; return 0; }
bzoj 2216 [Poi2011]Lightning Conductor 決策單調性+dp