結果
問題 | No.705 ゴミ拾い Hard |
ユーザー | 草苺奶昔 |
提出日時 | 2023-12-03 00:42:38 |
言語 | Go (1.22.1) |
結果 |
AC
|
実行時間 | 447 ms / 1,500 ms |
コード長 | 4,548 bytes |
コンパイル時間 | 12,196 ms |
コンパイル使用メモリ | 230,488 KB |
実行使用メモリ | 17,280 KB |
最終ジャッジ日時 | 2024-09-26 21:52:29 |
合計ジャッジ時間 | 21,386 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
5,248 KB |
testcase_01 | AC | 1 ms
5,248 KB |
testcase_02 | AC | 1 ms
5,376 KB |
testcase_03 | AC | 1 ms
5,376 KB |
testcase_04 | AC | 1 ms
5,376 KB |
testcase_05 | AC | 1 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 1 ms
5,376 KB |
testcase_08 | AC | 1 ms
5,376 KB |
testcase_09 | AC | 1 ms
5,376 KB |
testcase_10 | AC | 1 ms
5,376 KB |
testcase_11 | AC | 1 ms
5,376 KB |
testcase_12 | AC | 1 ms
5,376 KB |
testcase_13 | AC | 1 ms
5,376 KB |
testcase_14 | AC | 2 ms
5,376 KB |
testcase_15 | AC | 2 ms
5,376 KB |
testcase_16 | AC | 3 ms
5,376 KB |
testcase_17 | AC | 3 ms
5,376 KB |
testcase_18 | AC | 3 ms
5,376 KB |
testcase_19 | AC | 3 ms
5,376 KB |
testcase_20 | AC | 3 ms
5,376 KB |
testcase_21 | AC | 3 ms
5,376 KB |
testcase_22 | AC | 3 ms
5,376 KB |
testcase_23 | AC | 2 ms
5,376 KB |
testcase_24 | AC | 447 ms
16,420 KB |
testcase_25 | AC | 442 ms
16,512 KB |
testcase_26 | AC | 441 ms
16,512 KB |
testcase_27 | AC | 446 ms
16,512 KB |
testcase_28 | AC | 441 ms
16,512 KB |
testcase_29 | AC | 445 ms
16,512 KB |
testcase_30 | AC | 439 ms
16,384 KB |
testcase_31 | AC | 410 ms
16,384 KB |
testcase_32 | AC | 432 ms
16,384 KB |
testcase_33 | AC | 315 ms
13,696 KB |
testcase_34 | AC | 315 ms
13,696 KB |
testcase_35 | AC | 343 ms
15,232 KB |
testcase_36 | AC | 389 ms
16,384 KB |
testcase_37 | AC | 345 ms
15,232 KB |
testcase_38 | AC | 389 ms
16,384 KB |
testcase_39 | AC | 414 ms
16,384 KB |
testcase_40 | AC | 1 ms
5,376 KB |
testcase_41 | AC | 1 ms
5,376 KB |
testcase_42 | AC | 1 ms
5,376 KB |
testcase_43 | AC | 429 ms
17,280 KB |
ソースコード
package main import ( "bufio" "fmt" "os" ) func main() { Yuki705() } // https://yukicoder.me/problems/no/705 func Yuki705() { in := bufio.NewReader(os.Stdin) out := bufio.NewWriter(os.Stdout) defer out.Flush() var n int fmt.Fscan(in, &n) A := make([]int, n) X := make([]int, n) Y := make([]int, n) for i := 0; i < n; i++ { fmt.Fscan(in, &A[i]) } for i := 0; i < n; i++ { fmt.Fscan(in, &X[i]) } for i := 0; i < n; i++ { fmt.Fscan(in, &Y[i]) } cubic := func(x int) int { return abs(x * x * x) } // 人i,垃圾j dist := func(i, j int) int { return cubic(X[j]-A[i]) + cubic(Y[j]) } f := func(i, j int) int { return dist(j-1, i) } fmt.Fprintln(out, MongeShortestPath(n, f)[n]) } func abs(x int) int { if x < 0 { return -x } return x } const INF int = 1e18 // Monge图最短路.求从0点出发到各个点的最短路. // O(nlogn). // f(i,j) : 边权函数, 即从i到j的边的权值(0<=i<j<=n). // https://noshi91.hatenablog.com/entry/2023/02/18/005856 func MongeShortestPath(n int, f func(i, j int) int) []int { dp := make([]int, n+1) for i := range dp { dp[i] = INF } x := make([]int, n+1) check := func(from, to int) { if from >= to { return } cost := f(from, to) if tmp := dp[from] + cost; tmp < dp[to] { dp[to] = tmp x[to] = from } } var dfs func(int, int) dfs = func(l, r int) { if l+1 >= r { return } m := (l + r) / 2 for i := x[l]; i <= x[r]; i++ { check(i, m) } dfs(l, m) for i := l + 1; i <= m; i++ { check(i, r) } dfs(m, r) } dp[0] = 0 check(0, n) dfs(0, n) return dp } // Monge图d边最短路. // O(nlogn)求从0到n-1恰好经过d条边的最短路,其中边权f(from,to)满足Monge性质. // f(i,j) : 边权函数, 即从i到j的边的权值(0<=i<j<=n). // maxWeight: 边权的最大值. // 返回值为从0到N恰好经过d条边的最短路. func MongeShortestPathDEdge(n, d, maxWeight int, f func(i, j int) int) int { if d > n { panic("d > N") } cal := func(x int) int { g := func(frm, to int) int { return f(frm, to) + x } cost := MongeShortestPath(n, g)[n] return cost - x*d } _, res := FibonacciSearch(cal, -3*maxWeight, 3*maxWeight+1, false) return res } // monge图d边最短路的d=1,...,N的答案. // 无法到达的点的距离为INF. // f(i,j) : 边权函数, 即从i到j的边的权值(0<=i<j<=n). func EnumerateMongeDEdgeShortestPath(n int, f func(i, j int) int) []int { res := make([]int, n+1) for i := range res { res[i] = INF } dp := make([]int, n+1) for i := range dp { dp[i] = INF } dp[0] = 0 for d := 1; d <= n; d++ { midx := MonotoneMinima2(n+1, n+1, func(j, i int) int { if i < j { return dp[i] + f(i, j) } return INF }) for i := n; i >= d; i-- { dp[i] = dp[midx[i]] + f(midx[i], i) } res[d] = dp[n] } return dp } // 给定一个 n 行 m 列的矩阵. // minI=argmin_j(A[i][j]) 单调递增时, 返回 minI. // f(i, j, k) : // 比较 A[i][j] 和 A[i][k] (保证 j < k) // 当 A[i][j] <= A[i][k] 时返回 true. func MonotoneMinima(row, col int, f func(i, j, k int) bool) []int { res := make([]int, row) var dfs func(int, int, int, int) dfs = func(is, ie, l, r int) { if is == ie { return } i := (is + ie) / 2 m := l for k := l + 1; k < r; k++ { if !f(i, m, k) { m = k } } res[i] = m dfs(is, i, l, m+1) dfs(i+1, ie, m, r) } dfs(0, row, 0, col) return res } // 给定一个 n 行 m 列的矩阵. // minI=argmin_j(A[i][j]) 单调递增时, 返回 minI. // get(i, j) : 返回 A[i][j] 的函数 func MonotoneMinima2(row, col int, get func(i, j int) int) []int { f := func(i, j, k int) bool { return get(i, j) <= get(i, k) } return MonotoneMinima(row, col, f) } // 寻找[start,end)中的一个极值点,不要求单峰性质. // // 返回值: (极值点,极值) func FibonacciSearch(f func(x int) int, start, end int, minimize bool) (int, int) { end-- a, b, c, d := start, start+1, start+2, start+3 n := 0 for d < end { b = c c = d d = b + c - a n++ } get := func(i int) int { if end < i { return INF } if minimize { return f(i) } return -f(i) } ya, yb, yc, yd := get(a), get(b), get(c), get(d) for i := 0; i < n; i++ { if yb < yc { d = c c = b b = a + d - c yd = yc yc = yb yb = get(b) } else { a = b b = c c = a + d - b ya = yb yb = yc yc = get(c) } } x := a y := ya if yb < y { x = b y = yb } if yc < y { x = c y = yc } if yd < y { x = d y = yd } if minimize { return x, y } return x, -y }