NOI2014 購票 樹上斜率優化

2022-09-18 11:15:28 字數 3138 閱讀 4307

首先易得方程,且經過變換有

$$\begin f_i &= \min\limits_ \ \\ f_j &= p_idist_j + f_i - dist_ip_i - q_i \end$$

在一條直線上時,斜率優化可以用普通$cdq$分治實現(會不會過於麻煩?),那麼對於在樹上斜率優化時,考慮點分治

這時就在點分治中運用$cdq$分治的思想,即使用在當前重心管轄範圍內的通向根節點的那一條鏈上的節點來更新其它節點就好了

注意在分治中的斜率優化時在凸包上加點和更新右側節點答案要同時進行,不然當前最優解可能會在後面由於斜率被刪去,導致答案錯誤,還有由於下面**是由深度由小到大處理的,所以是反著維護下凸包,即上凸包

1 #include 2 #include 3 #include 4 #include 5 #include 6

7using

namespace

std;

89 typedef long

long

ll;10

11const

int maxn = 2e05 + 10;12

const

int maxm = 2e05 + 10;13

14const

int inf = 0x7fffffff;15

const ll infll = 0x3f3f3f3f3f3f3f3f;16

const

double eps = 1e-08;17

18int dcmp (double

p) 23

24struct

linkedforwardstar ;

2930 linkedforwardstar link[maxm << 1

];31

int head[maxn]= ;

32int size = 0;33

34void insert (int u, int

v) 40

41const

int root = 1;42

43struct

cityst

47} ;

48cityst city[maxn];

4950

ll f[maxn];

5152

intn;

53 ll fdist[maxn]= ;

5455 ll dist[maxn]= ;

56int father[maxn]= ;

57void dfs (int root, int

father) 65}

6667

int vis[maxn]= ;

6869

int size[maxn]= ;

70int grvy, minval =inf;

71int

total;

72void grvy_acqu (int root, int

father)

83 maxpart = max (maxpart, total -size[root]);

84if (maxpart

85 grvy = root, minval =maxpart;86}

8788

inttemp[maxn];

89int p = 0;90

intque[maxn];

91double slope (int a, int

b) 96

intlistq[maxn];

97int lp = 0;98

bool comp (const

int& a, const

int&b)

101void listq_acqu (int root, int

father)

110}

111int binary_search (int left, int right, int

p) 122

return

l;123

}124

void update (int left, int right, int

tp)

130void solve (int

root)

138 p = 0

;139 temp[++ p] =fgrvy;

140for (int nd = fgrvy; nd != root; nd =father[nd])

145 lp = 0

;146 listq_acqu (fgrvy, 0

);147 sort (listq + 1, listq + lp + 1

, comp);

148int left = 1, right = 0

;149

int j = 1

;150

for (int i = 1; i <= p && j <= lp; i ++)

157while (j <=lp)

158 update (left, right, listq[j ++]);

159for (int i = head[fgrvy]; i; i =link[i].next)

165}

166167

intgetint ()

178179

ll getll ()

190191

intmain ()

205 dfs (root, 0

);206 size[root] =n;

207solve (root);

208for (int i = 2; i <= n; i ++)

209 printf ("

%lld\n

", f[i]);

210211

return0;

212}

213214

/*215

7 3216

1 2 20 0 3

2171 5 10 100 5

2182 4 10 10 10

2192 9 1 100 10

2203 5 20 100 10

2214 4 20 0 10

222*/

view code

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...

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...

Noi2014 購票 斜率優化DP 可持久化凸包

貌似網上大部分題解都是cdq分治 點分治然後再斜率優化dp,我貌似並沒有用這個方法。這一題跟這題有點像,只不過多了乙個l的限制 如果說直接跑斜率優化dp,儲存整個序列的話,顯然是不行的,如圖所示 圖鳴謝某巨佬 所以我們需要種一棵線段樹,每個線段樹內儲存乙個存當前區間凸包的單調棧,彈出插入操作跟剛剛說...