先推出動態轉移方程方程,它有乙個距離限制,這一維可以用線段樹維護,然後線段樹中的凸包要求有回溯操作,這個每次只會修改top和那一為的值,記錄一下即可。(bzoj上tle了。。。
#include #include #include #include #include #define rep(i, x, y) for (int i = x; i <= y; i ++)
#define dwn(i, x, y) for (int i = x; i >= y; i --)
#define repe(i, x) for(int i = pos[x]; i; i = g[i].nex)
#define pb push_back
#define u t[x]
#define lc t[x + x]
#define rc t[x + x + 1]
using namespace std;
typedef long long ll;
typedef long double db;
const int n = 200005;
const ll inf = 1ll << 62;
struct edge g[n], g2[n*30], gx[n*30];
struct seg_node t[n*8];
int n, t0, pos[n], sz, sz2, p1[n*4], szx, p0[n*4], fa[n];
ll qx, qy, lz[n], a[n], b[n], l[n], lt[n], f[n], q, h[n];
void init(int x, int y) , pos[x] = sz; }
void add1(int x, ll y) , p1[x] = sz2; }
void add2(int x, ll y, ll z) , p0[x] = szx; }
ll qry(int x, int l, int r)
return (-u.qx[l] * b[qx]) + u.qy[l];
} int mid = l + r >> 1;
return min(qry(x + x, l, mid), qry(x + x + 1, mid + 1, r));
}bool cmp(ll x1, ll y1, ll x2, ll y2, ll x3, ll y3)
void upd(int x)
void ins(int x, int l, int r) u.tl = tl + 1;
if (l == r)
int mid = l + r >> 1;
if (q <= mid) ins(x + x, l, mid); else ins(x + x + 1, mid + 1, r); upd(x);
}void era(int x, int l, int r)
int mid = l + r >> 1;
if (q <= mid) era(x + x, l, mid); else era(x + x + 1, mid + 1, r); upd(x);
}void dfs(int x)
q = h[x], qx = lt[x], qy = f[x]; ins(1, 1, n);
repe(i, x)
q = h[x]; era(1, 1, n);
}int main()
h[1] = 1, dfs(1);
rep(i, 2, n) printf("%lld\n", f[i]);
return 0;
}
題解 NOI2014購票
我們首先get出斜率優化方程 dp v dis v p u dis u p u q u dp u left 0 dis u dis v lim u right 那麼 y dp v x dis v k p u 我們所要做的就是維護乙個下凸包以維護最小的b值。現在有兩個本題的難點 首先,轉移到 u 點的...
NOI2014 購票 樹上斜率優化
首先易得方程,且經過變換有 begin f i min limits f j p idist j f i dist ip i q i end 在一條直線上時,斜率優化可以用普通 cdq 分治實現 會不會過於麻煩?那麼對於在樹上斜率優化時,考慮點分治 這時就在點分治中運用 cdq 分治的思想,即使用在...
NOI2014 購票(樹形dp 樹剖 斜率優化)
考慮樹形 dp,設 dpi dp i dpi 為 ii i 節點到 sz 市的最小費用,dis idis i disi 為 sz 市到 i ii 節點的距離。顯然初始化 dp1 0 dp 1 0 dp1 0 然後 dis idis i disi 可以提前預處理出來。然後有 dpu min dpv d...