我們首先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\)點的\(v\)點必須是u的祖先,且兩者之間相距的距離在一定的限制範圍之內。如何滿足?我們想到,既然需要維護一定範圍內的乙個凸包,那麼我們可以借助資料結構來完成。線段樹可以做到:乙個線段樹上的節點代表從(l ~ r)這段區間內的節點所構成的凸包,那麼任何乙個區間都可以由線段樹上上的節點湊成,取每乙個中間的最大值即可。
所以我們的線段樹所維護的即為一條鏈上的節點(按深度遞增編號)。但還有乙個問題沒有解決:當我們將乙個節點加入凸包的時候我們會為了維護凸包的凸性而彈出一些節點(包括在這個節點的子樹都處理完畢之後,該節點自身也要離開凸包,因為它不再屬於鏈上的節點)。那麼在處理完之後,我們就希望能夠將線段樹還原回訪問它之前的樣子——先想想普通的維護做法:從單調佇列的隊尾不斷彈出元素,直到凸包合法為止。仔細考慮這個過程,我們可以將操作簡化為:找到最後乙個彈出的元素(a), 意思就是彈出元素(a)後加入當前元素(b)(用(b)替換(a)),再更新隊尾指標的指向。所以我們只需要對於每乙個節點都維護一下它所彈出的節點&修改的隊尾位置就可以了,最後再還原回去。
以下**——注意inf大大大大大……就這裡調了我三個小時,直到我發現了修改inf讀到的值竟然不一樣的驚天大秘密……σ(っ°д°;)っ
#include usingnamespace
std;
#define maxn 200050
#define lgmaxn 25
#define inf 99999999999999999ll
#define ll long long
#define db double
intn, t;
ll p[maxn], q[maxn], dp[maxn], dis[maxn], len[maxn];
ll x[maxn], y[maxn], last = 0
; int q[maxn * 50
], dep[maxn], degree[maxn];
int cnp = 1
, head[maxn], maxx;
struct
tree
t[maxn * 20
];struct
edge
e[maxn];
struct
node
s[maxn][lgmaxn];
void add(int u, int v, int
w)db get_s(
int a, int
b)void build(int p, int l, int
r)void update(int p, int l, int r, int k, int tot, node *a)
t ++; a[++ tot] =(node) ;
q[t] =k;
if(l == r) return
;
int mid = (l + r) >> 1
;
if(k <= mid) update(p << 1
, l, mid, k, tot, a);
else update(p << 1 | 1, mid + 1
, r, k, tot, a);
}int check(int h, int t, int
k)
return
q[ans];
}ll query(
intp, ll lim, ll k)
else
return min(query(p << 1, lim, k), query(p << 1 | 1
, lim, k));
}void rebound(int p, int l, int r, int k, int tot, node *a)
void dfs(int u, int
fa, ll co)
rebound(
1, 1, n, dep[u], 1
, s[dep[u]]);
x[dep[u]] = y[dep[u]] = dis[dep[u]] =inf;
}}int
main()
build(
1, 1
, n);
dfs(
1, 0, 0
);
for(int i = 2; i <= n; i ++)
printf(
"%lld\n
", dp[i]);
return0;
}
NOI2014 購票 線段樹做法
先推出動態轉移方程方程,它有乙個距離限制,這一維可以用線段樹維護,然後線段樹中的凸包要求有回溯操作,這個每次只會修改top和那一為的值,記錄一下即可。bzoj上tle了。include include include include include define rep i,x,y for int ...
NOI2014 購票 樹上斜率優化
首先易得方程,且經過變換有 begin f i min limits f j p idist j f i dist ip i q i end 在一條直線上時,斜率優化可以用普通 cdq 分治實現 會不會過於麻煩?那麼對於在樹上斜率優化時,考慮點分治 這時就在點分治中運用 cdq 分治的思想,即使用在...
NOI2014 魔法森林題解
這道題正解其實是lct,然而貌似spfa也可以成功水過,所以根本不知道lct的我只能說spfa了。這道題最大的限制是兩種精靈就意味著一條道可能有兩個權值,因此我們需要去將其中乙個固定,然後再推另乙個權值,也就是說,我們可以,列舉每一條邊的a,然後只走a值不大於他的邊。然而並沒有那麼容易,本題資料極大...