Submission #6536941


Source Code Expand

;; -*- coding: utf-8 -*-
(eval-when (:compile-toplevel :load-toplevel :execute)
  (defparameter OPT
    #+swank '(optimize (speed 3) (safety 2))
    #-swank '(optimize (speed 3) (safety 0) (debug 0)))
  #+swank (ql:quickload '(:cl-debug-print :fiveam))
  #-swank (set-dispatch-macro-character #\# #\> (lambda (s c p) (declare (ignore c p)) (read s nil (values) t))))
#+swank (cl-syntax:use-syntax cl-debug-print:debug-print-syntax)
#-swank (disable-debugger) ; for CS Academy

;; BEGIN_INSERTED_CONTENTS
;; Should we do this with UNWIND-PROTECT?
(defmacro with-buffered-stdout (&body body)
  "Buffers all outputs to *STANDARD-OUTPUT* in BODY and flushes them to
*STANDARD-OUTPUT* after BODY has been done (without error). Note that only
BASE-CHAR is allowed."
  (let ((out (gensym)))
    `(let ((,out (make-string-output-stream :element-type 'base-char)))
       (let ((*standard-output* ,out))
         ,@body)
       (write-string (get-output-stream-string ,out)))))

;;;
;;; Disjoint set by Union-Find algorithm
;;;

(defstruct (disjoint-set
            (:constructor make-disjoint-set
                (size &aux (data (make-array size :element-type 'fixnum :initial-element -1))))
            (:conc-name ds-))
  (data nil :type (simple-array fixnum (*))))

(declaim (ftype (function * (values (mod #.array-total-size-limit) &optional)) ds-root))
(defun ds-root (x disjoint-set)
  "Returns the root of X."
  (declare (optimize (speed 3) (safety 0))
           ((mod #.array-total-size-limit) x))
  (let ((data (ds-data disjoint-set)))
    (if (< (aref data x) 0)
        x
        (setf (aref data x)
              (ds-root (aref data x) disjoint-set)))))

(declaim (inline ds-unite!))
(defun ds-unite! (x1 x2 disjoint-set)
  "Destructively unites X1 and X2 and returns true iff X1 and X2 become
connected for the first time."
  (let ((root1 (ds-root x1 disjoint-set))
        (root2 (ds-root x2 disjoint-set)))
    (unless (= root1 root2)
      (let ((data (ds-data disjoint-set)))
        ;; ensure the size of root1 >= the size of root2
        (when (> (aref data root1) (aref data root2))
          (rotatef root1 root2))
        (incf (aref data root1) (aref data root2))
        (setf (aref data root2) root1)))))

(declaim (inline ds-connected-p))
(defun ds-connected-p (x1 x2 disjoint-set)
  "Returns true iff X1 and X2 have the same root."
  (= (ds-root x1 disjoint-set) (ds-root x2 disjoint-set)))

(declaim (inline ds-size))
(defun ds-size (x disjoint-set)
  "Returns the size of the connected component to which X belongs."
  (- (aref (ds-data disjoint-set)
           (ds-root x disjoint-set))))

(declaim (ftype (function * (values fixnum &optional)) read-fixnum+))
(defun read-fixnum+ (&optional (in *standard-input*))
  (declare #.OPT)
  (macrolet ((%read-byte ()
               `(the (unsigned-byte 8)
                     #+swank (char-code (read-char in nil #\Nul))
                     #-swank (sb-impl::ansi-stream-read-byte in nil #.(char-code #\Nul) nil))))
    (let* ((result (loop (let ((byte (%read-byte)))
                           (cond ((<= 48 byte 57)
                                  (return (- byte 48)))
                                 ((zerop byte) ; #\Nul
                                  (error "Read EOF or #\Nul.")))))))
      (declare ((integer 0 #.most-positive-fixnum) result))
      (loop
        (let* ((byte (%read-byte)))
          (if (<= 48 byte 57)
              (setq result (+ (- byte 48) (* 10 (the (integer 0 #.(floor most-positive-fixnum 10)) result))))
              (return result)))))))

(defmacro dbg (&rest forms)
  #+swank
  (if (= (length forms) 1)
      `(format *error-output* "~A => ~A~%" ',(car forms) ,(car forms))
      `(format *error-output* "~A => ~A~%" ',forms `(,,@forms)))
  #-swank (declare (ignore forms)))

(defmacro define-int-types (&rest bits)
  `(progn
     ,@(mapcar (lambda (b) `(deftype ,(intern (format nil "UINT~A" b)) () '(unsigned-byte ,b))) bits)
     ,@(mapcar (lambda (b) `(deftype ,(intern (format nil "INT~A" b)) () '(signed-byte ,b))) bits)))
(define-int-types 2 4 7 8 15 16 31 32 62 63 64)

(declaim (inline println))
(defun println (obj &optional (stream *standard-output*))
  (let ((*read-default-float-format* 'double-float))
    (prog1 (princ obj stream) (terpri stream))))

(defconstant +mod+ 1000000007)

;; Body


(declaim (inline map-binsorted))
(defun map-binsorted (function sequence range-max &key from-end key)
  (declare ((mod #.array-total-size-limit) range-max))
  (let ((counts (make-array (1+ range-max) :element-type 'list :initial-element nil))
        (existing-min most-positive-fixnum)
        (existing-max 0))
    (declare (dynamic-extent counts))
    (sequence:dosequence (e sequence)
      (let ((key (funcall key e)))
        (push e (aref counts key))
        (when (< key existing-min) (setf existing-min key))
        (when (< existing-max key) (setf existing-max key))))
    (if from-end
        (loop for v from existing-max downto existing-min
              do (dolist (e (aref counts v))
                   (funcall function e)))
        (loop for v from existing-min to existing-max
              do (dolist (e (aref counts v))
                   (funcall function e))))))

(defmacro do-binsorted ((var sequence range-max &key from-end key finally) &body body)
  "DO-style macro of MAP-BINSORTED"
  `(block nil
     (map-binsorted (lambda (,var) ,@body) ,sequence ,range-max
                    :key ,key
                    :from-end ,from-end)
     ,finally))

(defun main ()
  (declare #.OPT
           (inline sort))
  (let* ((n (read))
         (m (read))
         (adj (make-array (list n n) :element-type 'uint32 :initial-element #xffffffff))
         (msts (make-array n :element-type 'list :initial-element nil))
         (dset (make-disjoint-set n))
         (buckets (make-array 100001 :element-type 'list)))
    (declare (uint31 n m))
    (dotimes (i m)
      (let ((u (read-fixnum+))
            (v (read-fixnum+))
            (w (read-fixnum+)))
        (setf (aref adj u v) w
              (aref adj v u) w)))
    (with-buffered-stdout
      (dotimes (_ (the uint32 (read)))
        (let ((p (read-fixnum+))
              (q (read-fixnum+))
              pset
              qset
              edges
              new-edges
              (tmp-dset (make-disjoint-set n))
              (res 0))
          (declare (uint32 res))
          (dotimes (i n)
            (when (ds-connected-p i p dset)
              (push i pset))
            (when (ds-connected-p i q dset)
              (push i qset)))
          (dolist (v1 pset)
            (dolist (v2 qset)
              (unless (= #xffffffff (aref adj v1 v2))
                (push (list* (aref adj v1 v2) v1 v2) edges))))
          (dolist (e (aref msts p))
            (push e edges))
          (dolist (e (aref msts q))
            (push e edges))
          (dotimes (i (length buckets))
            (setf (aref buckets i) nil))
          (let ((existing-min most-positive-fixnum)
                (existing-max 0))
            (dolist (e edges)
              (let ((cost (car e)))
                (push e (aref buckets cost))
                (when (< cost existing-min) (setf existing-min cost))
                (when (< existing-max cost) (setf existing-max cost))))
            (loop for v from existing-min to existing-max
                  do (dolist (node (aref buckets v))
                       (let ((cost (car node))
                             (edge (cdr node)))
                         (unless (ds-connected-p (car edge) (cdr edge) tmp-dset)
                           (ds-unite! (car edge) (cdr edge) tmp-dset)
                           (push node new-edges)
                           (incf res (the uint32 cost)))))))
          (if (= (+ (length pset) (length qset))
                 (ds-size p tmp-dset))
              (println res)
              (write-line "IMPOSSIBLE"))
          (ds-unite! p q dset)
          (dolist (i pset)
            (setf (aref msts i) new-edges))
          (dolist (i qset)
            (setf (aref msts i) new-edges)))))))

#-swank (main)

Submission Info

Submission Time
Task F - 魔法の糸
User sansaqua
Language Common Lisp (SBCL 1.1.14)
Score 200
Code Size 8297 Byte
Status AC
Exec Time 840 ms
Memory 82660 KiB

Judge Result

Set Name All
Score / Max Score 200 / 200
Status
AC × 31
Set Name Test Cases
All 00-sample1, 00-sample2, 01-random-small-tree01, 01-random-small-tree02, 02-random-small-sparse01, 02-random-small-sparse02, 02-random-small-sparse03, 03-random-small-dense01, 03-random-small-dense02, 03-random-small-dense03, 03-random-small-dense04, 03-random-small-dense05, 11-random-large-tree01, 11-random-large-tree02, 11-random-large-tree03, 12-random-large-sparse01, 12-random-large-sparse02, 12-random-large-sparse03, 13-random-large-denseA01, 13-random-large-denseA02, 13-random-large-denseA03, 13-random-large-denseA04, 14-random-large-denseB01, 14-random-large-denseB02, 14-random-large-denseB03, 14-random-large-denseB04, 15-random-large-denseC01, 15-random-large-denseC02, 20-kill-naive, 21-kill-loop, 23-min
Case Name Status Exec Time Memory
00-sample1 AC 270 ms 35816 KiB
00-sample2 AC 114 ms 23144 KiB
01-random-small-tree01 AC 121 ms 25188 KiB
01-random-small-tree02 AC 122 ms 25188 KiB
02-random-small-sparse01 AC 121 ms 25192 KiB
02-random-small-sparse02 AC 121 ms 25184 KiB
02-random-small-sparse03 AC 122 ms 25184 KiB
03-random-small-dense01 AC 122 ms 25188 KiB
03-random-small-dense02 AC 122 ms 25192 KiB
03-random-small-dense03 AC 122 ms 25188 KiB
03-random-small-dense04 AC 122 ms 25188 KiB
03-random-small-dense05 AC 121 ms 25188 KiB
11-random-large-tree01 AC 674 ms 80612 KiB
11-random-large-tree02 AC 672 ms 80612 KiB
11-random-large-tree03 AC 666 ms 80612 KiB
12-random-large-sparse01 AC 705 ms 80612 KiB
12-random-large-sparse02 AC 707 ms 80612 KiB
12-random-large-sparse03 AC 711 ms 80612 KiB
13-random-large-denseA01 AC 823 ms 80612 KiB
13-random-large-denseA02 AC 825 ms 80612 KiB
13-random-large-denseA03 AC 831 ms 80608 KiB
13-random-large-denseA04 AC 840 ms 80612 KiB
14-random-large-denseB01 AC 590 ms 82660 KiB
14-random-large-denseB02 AC 583 ms 80612 KiB
14-random-large-denseB03 AC 592 ms 80612 KiB
14-random-large-denseB04 AC 584 ms 80616 KiB
15-random-large-denseC01 AC 569 ms 80612 KiB
15-random-large-denseC02 AC 568 ms 80616 KiB
20-kill-naive AC 612 ms 80484 KiB
21-kill-loop AC 631 ms 82532 KiB
23-min AC 113 ms 23136 KiB