結果

問題 No.2764 Warp Drive Spacecraft
ユーザー PNJPNJ
提出日時 2024-05-17 22:58:52
言語 PyPy3
(7.3.15)
結果
TLE  
(最新)
AC  
(最初)
実行時間 -
コード長 7,063 bytes
コンパイル時間 173 ms
コンパイル使用メモリ 82,692 KB
実行使用メモリ 170,596 KB
最終ジャッジ日時 2024-05-18 00:11:49
合計ジャッジ時間 28,271 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 71 ms
69,012 KB
testcase_01 AC 68 ms
70,600 KB
testcase_02 AC 68 ms
69,336 KB
testcase_03 AC 68 ms
70,456 KB
testcase_04 AC 67 ms
69,136 KB
testcase_05 AC 76 ms
69,488 KB
testcase_06 AC 71 ms
70,060 KB
testcase_07 AC 72 ms
69,804 KB
testcase_08 AC 68 ms
69,684 KB
testcase_09 AC 68 ms
70,000 KB
testcase_10 AC 119 ms
78,340 KB
testcase_11 AC 72 ms
70,588 KB
testcase_12 AC 120 ms
78,896 KB
testcase_13 AC 134 ms
79,116 KB
testcase_14 AC 69 ms
69,488 KB
testcase_15 AC 67 ms
70,292 KB
testcase_16 AC 476 ms
131,596 KB
testcase_17 AC 515 ms
131,852 KB
testcase_18 AC 509 ms
128,848 KB
testcase_19 AC 2,282 ms
139,840 KB
testcase_20 AC 1,986 ms
140,868 KB
testcase_21 AC 1,846 ms
140,876 KB
testcase_22 AC 1,955 ms
141,408 KB
testcase_23 AC 2,396 ms
140,212 KB
testcase_24 AC 2,290 ms
142,916 KB
testcase_25 AC 2,149 ms
141,256 KB
testcase_26 AC 2,930 ms
165,864 KB
testcase_27 AC 2,750 ms
164,956 KB
testcase_28 TLE -
testcase_29 AC 2,880 ms
167,756 KB
testcase_30 AC 2,803 ms
164,252 KB
testcase_31 AC 2,870 ms
170,596 KB
testcase_32 TLE -
testcase_33 AC 799 ms
107,676 KB
testcase_34 AC 816 ms
107,108 KB
testcase_35 AC 841 ms
106,888 KB
testcase_36 AC 1,327 ms
137,544 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

import heapq

def dijkstra(s, n, edge):
    dist = [1 << 63]*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)
0