點此看題
首先可以用暴力dpdp
dp艹過去,設dp[
i][j
]dp[i][j]
dp[i][
j]為到了i
ii點的時間是j
jj的最小花費,由於時間是單向流逝的,我們可以先把邊按出發時間排序,用邊轉移,列舉到達出發點的時間jjj:
d p[
y[i]
][q[
i]]=
dp[x
[i]]
[j]+
cost
(p[i
]−j)
dp[y[i]][q[i]]=dp[x[i]][j]+cost(p[i]-j)
dp[y[i
]][q
[i]]
=dp[
x[i]
][j]
+cos
t(p[
i]−j
)但是人總要追求正解,設dp[
i]
dp[i]
dp[i
]為正好走過第i
ii條邊的最小花費,轉移列舉上一次走過的邊j
jj,轉移需要滿足條件:qj≤
pi,y
[j]=
x[i]
q_j\leq p_i,y[j]=x[i]
**≤pi
,y[
j]=x
[i],方程式如下:
d p[
i]=d
p[j]
+a(p
[i]−
q[j]
)2+b
(p[i
]−q[
j])+
cdp[i]=dp[j]+a(p[i]-q[j])^2+b(p[i]-q[j])+c
dp[i]=
dp[j
]+a(
p[i]
−q[j
])2+
b(p[
i]−q
[j])
+c這種平方轉移好像能推斜率式,設轉移點j
>
kj>k
j>
k,且j
jj決策點優(給結論):
d p[
j]+a
q[j]
2−bq
[j]−
dp[k
]−q[
k]2+
bq[k
]q[j
]−q[
k]
<2a
p[i]
\frac<2ap[i]
q[j]−q
[k]d
p[j]
+aq[
j]2−
bq[j
]−dp
[k]−
q[k]
2+bq
[k]
<2a
p[i]
畫個圖可以發現斜率是單調遞增的,但是現在的轉移順序問題還是有些蛋疼,觀察我們轉移需要的兩個條件,我們可以先滿足第二個條件,也就是維護n
nn個凸包,詢問的時候到對應的凸包裡面查詢。那第乙個條件怎麼辦?我們轉移的時候先列舉邊的出發時間,插入凸包的時候只插入結束時間不超過它的,這樣凸包裡的東西就滿足第乙個條件了。
時間複雜度o(m
)o(m)
o(m)
,凸包需要vec
to
r\tt vector
vector
#include
#include
#include
using
namespace std;
const
int m =
200005
;int
read()
while
(c>=
'0'&& c<=
'9')
return x*f;
}int n,m,ans,a,b,c,x[m]
,y[m]
,p[m]
,q[m]
,h[m]
,t[m]
,dp[m]
;vector<
int> q[m]
,a[m]
;queue<
int> b[m]
;intup(
int j,
int k)
intdown
(int j,
int k)
void
ins(
int u,
int i)
//在u凸包插入i
void
****
(int u,
int i)
//在u凸包中把不滿足i的艹出去
signed
main()
ans=
1e18
;for
(int i=
2;i<=n;i++
) t[i]=-
1;q[1].
push_back(0
);for(
int t=
0;t<=
1000
;t++
)for
(int i=
0;i.size()
;i++)}
printf
("%d\n"
,ans);}
/*dp[i]=min(dp[j]+a(pi-**)^2+b(pi-**)+c) x[i]=y[j]
j在後,j優
dp[j]+a(pi-**)^2+b(pi-**)
NOI2019 回家路線
link solution 演算法一通過觀察範圍發現 q leq1000 所以直接暴力拆點 dp 時間複雜度 o 1000m o 能過 演算法二因為有 a times x 2 b times x c 考慮斜率優化。設 f i 表示走完第 i 條邊的最小煩躁值,則 f i min space u i ...
NOI2019 回家路線(最短路,斜率優化)
終於把這鬼玩意弄完了 為什麼寫的這麼醜 順便吐槽 routesea 最短路的狀態很顯然 f i 表示從第 i 條線下來的最小代價。首先明顯要把那個式子拆開。直覺告訴我們這應該是個斜率優化。f i min f j a p i q j 2 b p i q j c x i y j,p i ge q j f...
LOJ 3156 NOI2019 回家路線
傳送門 明明可以bfs bfsbf s寫了個dij dijdi j把自己強行玩wawa wa有2種做法 第一種 考慮對於同乙個點的入邊i,j i,ji,j轉移給出邊xxx 把式子列出來後發現是乙個標準的斜率優化 在凸包上二分就可以了 複雜度o m logm o mlogm o mlog m 第二種 ...