結果
問題 | No.2764 Warp Drive Spacecraft |
ユーザー | PNJ |
提出日時 | 2024-05-17 22:56:34 |
言語 | PyPy3 (7.3.15) |
結果 |
WA
|
実行時間 | - |
コード長 | 7,068 bytes |
コンパイル時間 | 363 ms |
コンパイル使用メモリ | 82,404 KB |
実行使用メモリ | 170,936 KB |
最終ジャッジ日時 | 2024-05-17 22:57:22 |
合計ジャッジ時間 | 35,791 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 63 ms
71,068 KB |
testcase_01 | AC | 59 ms
70,404 KB |
testcase_02 | AC | 60 ms
70,060 KB |
testcase_03 | WA | - |
testcase_04 | AC | 58 ms
69,876 KB |
testcase_05 | AC | 57 ms
70,344 KB |
testcase_06 | AC | 68 ms
70,268 KB |
testcase_07 | AC | 61 ms
69,872 KB |
testcase_08 | AC | 60 ms
69,828 KB |
testcase_09 | AC | 62 ms
70,844 KB |
testcase_10 | AC | 103 ms
79,148 KB |
testcase_11 | AC | 65 ms
70,932 KB |
testcase_12 | AC | 108 ms
78,852 KB |
testcase_13 | AC | 115 ms
79,592 KB |
testcase_14 | AC | 62 ms
69,064 KB |
testcase_15 | AC | 58 ms
70,444 KB |
testcase_16 | AC | 431 ms
131,792 KB |
testcase_17 | AC | 454 ms
132,300 KB |
testcase_18 | AC | 405 ms
123,584 KB |
testcase_19 | AC | 1,662 ms
140,200 KB |
testcase_20 | AC | 1,569 ms
140,908 KB |
testcase_21 | AC | 1,656 ms
141,380 KB |
testcase_22 | AC | 1,673 ms
141,640 KB |
testcase_23 | AC | 1,552 ms
140,460 KB |
testcase_24 | AC | 1,656 ms
142,696 KB |
testcase_25 | AC | 1,638 ms
141,492 KB |
testcase_26 | AC | 2,275 ms
166,288 KB |
testcase_27 | AC | 2,290 ms
164,940 KB |
testcase_28 | AC | 2,439 ms
166,532 KB |
testcase_29 | AC | 2,318 ms
167,792 KB |
testcase_30 | AC | 2,374 ms
164,620 KB |
testcase_31 | AC | 2,392 ms
170,936 KB |
testcase_32 | AC | 2,338 ms
170,076 KB |
testcase_33 | AC | 692 ms
107,724 KB |
testcase_34 | AC | 687 ms
106,896 KB |
testcase_35 | AC | 662 ms
107,648 KB |
ソースコード
import heapq def dijkstra(s, n, edge): dist = [float("Inf")]*n dist[s] = 0 hq = [[0,s]] heapq.heapify(hq) while len(hq) > 0: d,i = heapq.heappop(hq) if dist[i] < d: continue for j,d_1 in edge[i]: if dist[j] > (dist[i] + d_1): dist[j] = dist[i] + d_1 heapq.heappush(hq, [dist[j],j]) return dist import math from bisect import bisect_left, bisect_right from typing import Generic, Iterable, Iterator, List, Tuple, TypeVar, Optional T = TypeVar('T') class SortedMultiset(Generic[T]): BUCKET_RATIO = 16 SPLIT_RATIO = 24 def __init__(self, a: Iterable[T] = []) -> None: "Make a new SortedMultiset from iterable. / O(N) if sorted / O(N log N)" a = list(a) n = self.size = len(a) if any(a[i] > a[i + 1] for i in range(n - 1)): a.sort() bucket_size = int(math.ceil(math.sqrt(n / self.BUCKET_RATIO))) self.a = [a[n * i // bucket_size : n * (i + 1) // bucket_size] for i in range(bucket_size)] def __iter__(self) -> Iterator[T]: for i in self.a: for j in i: yield j def __reversed__(self) -> Iterator[T]: for i in reversed(self.a): for j in reversed(i): yield j def __eq__(self, other) -> bool: return list(self) == list(other) def __len__(self) -> int: return self.size def __repr__(self) -> str: return "SortedMultiset" + str(self.a) def __str__(self) -> str: s = str(list(self)) return "{" + s[1 : len(s) - 1] + "}" def _position(self, x: T) -> Tuple[List[T], int, int]: "return the bucket, index of the bucket and position in which x should be. self must not be empty." for i, a in enumerate(self.a): if x <= a[-1]: break return (a, i, bisect_left(a, x)) def __contains__(self, x: T) -> bool: if self.size == 0: return False a, _, i = self._position(x) return i != len(a) and a[i] == x def count(self, x: T) -> int: "Count the number of x." return self.index_right(x) - self.index(x) def add(self, x: T) -> None: "Add an element. / O(√N)" if self.size == 0: self.a = [[x]] self.size = 1 return a, b, i = self._position(x) a.insert(i, x) self.size += 1 if len(a) > len(self.a) * self.SPLIT_RATIO: mid = len(a) >> 1 self.a[b:b+1] = [a[:mid], a[mid:]] def _pop(self, a: List[T], b: int, i: int) -> T: ans = a.pop(i) self.size -= 1 if not a: del self.a[b] return ans def discard(self, x: T) -> bool: "Remove an element and return True if removed. / O(√N)" if self.size == 0: return False a, b, i = self._position(x) if i == len(a) or a[i] != x: return False self._pop(a, b, i) return True def lt(self, x: T) -> Optional[T]: "Find the largest element < x, or None if it doesn't exist." for a in reversed(self.a): if a[0] < x: return a[bisect_left(a, x) - 1] def le(self, x: T) -> Optional[T]: "Find the largest element <= x, or None if it doesn't exist." for a in reversed(self.a): if a[0] <= x: return a[bisect_right(a, x) - 1] def gt(self, x: T) -> Optional[T]: "Find the smallest element > x, or None if it doesn't exist." for a in self.a: if a[-1] > x: return a[bisect_right(a, x)] def ge(self, x: T) -> Optional[T]: "Find the smallest element >= x, or None if it doesn't exist." for a in self.a: if a[-1] >= x: return a[bisect_left(a, x)] def __getitem__(self, i: int) -> T: "Return the i-th element." if i < 0: for a in reversed(self.a): i += len(a) if i >= 0: return a[i] else: for a in self.a: if i < len(a): return a[i] i -= len(a) raise IndexError def pop(self, i: int = -1) -> T: "Pop and return the i-th element." if i < 0: for b, a in enumerate(reversed(self.a)): i += len(a) if i >= 0: return self._pop(a, ~b, i) else: for b, a in enumerate(self.a): if i < len(a): return self._pop(a, b, i) i -= len(a) raise IndexError def bisect(self, x: T) -> int: "Count the number of elements < x." ans = 0 for a in self.a: if a[-1] >= x: return ans + bisect_left(a, x) ans += len(a) return ans def index_right(self, x: T) -> int: "Count the number of elements <= x." ans = 0 for a in self.a: if a[-1] > x: return ans + bisect_right(a, x) ans += len(a) return ans class ConvexHullTrick: def __init__(self): self.L = SortedMultiset([]) self.n = 0 def check(self,a,b): if self.n == 0: return True x = self.L.bisect((a,b)) if x == 0: aa,bb = self.L[0] if a != aa: return True if b < bb: return True else: return False elif x == self.n: aa,bb = self.L[-1] if a != aa: return True if b < bb: return True else: return False else: al,bl = self.L[x-1] ar,br = self.L[x] if (br-b)*(a-al) >= (b-bl)*(ar-a): return True else: return False def add(self,a,b): # y=ax+bを追加する。 if self.check(a,b): x = self.L.bisect((a,b)) self.L.add((a,b)) self.n += 1 l = x - 1 r = x + 1 while r < self.n: a,b = self.L[r] self.L.discard((a,b)) self.n -= 1 if self.check(a,b): self.L.add((a,b)) self.n += 1 break while l > 0: a,b = self.L[l] self.L.discard((a,b)) l -= 1 self.n -= 1 if self.check(a,b): self.L.add((a,b)) self.n += 1 break def min(self,x): l = 0 r = self.n while r - l > 1: m = (l + r) // 2 a,b = self.L[m] aa,bb = self.L[m-1] if a*x + b <= aa*x + bb: l = m else: r = m a,b = self.L[l] return a*x + b def get(self): return self.L N,M = map(int,input().split()) W = list(map(int,input().split())) G = [[] for i in range(N)] for _ in range(M): u,v,t = map(int,input().split()) u,v = u - 1,v - 1 G[u].append((v,t)) G[v].append((u,t)) CHT = ConvexHullTrick() dist_s = dijkstra(0,N,G) dist_g = dijkstra(N-1,N,G) for i in range(N): w,d = W[i],dist_g[i] CHT.add(w,d) ans = dist_s[N-1] for i in range(N): w,d = W[i],dist_s[i] res = CHT.min(w) + d ans = min(ans,res) print(ans)