(in-package :cl-user) (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 :cp/util) :silent t) #+swank (use-package :cp/util :cl-user) #-swank (set-dispatch-macro-character #\# #\> (lambda (s c p) (declare (ignore c p)) `(values ,(read s nil nil t)))) #+sbcl (setq *random-state* (seed-random-state (nth-value 1 (get-time-of-day))))) #+swank (set-dispatch-macro-character #\# #\> #'cl-debug-print:debug-print-reader) (macrolet ((def (b) `(progn (deftype ,(intern (format nil "UINT~A" b)) () '(unsigned-byte ,b)) (deftype ,(intern (format nil "INT~A" b)) () '(signed-byte ,b)))) (define-int-types (&rest bits) `(progn ,@(mapcar (lambda (b) `(def ,b)) bits)))) (define-int-types 2 4 7 8 15 16 31 32 62 63 64)) (defconstant +mod+ 998244353) (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))) (declaim (inline println)) (defun println (obj &optional (stream *standard-output*)) (let ((*read-default-float-format* (if (typep obj 'double-float) 'double-float *read-default-float-format*))) (prog1 (princ obj stream) (terpri stream)))) ;; BEGIN_INSERTED_CONTENTS ;;; ;;; Arithmetic operations with static modulus ;;; (defpackage :cp/mod-operations (:use :cl) (:export #:define-mod-operations)) (in-package :cp/mod-operations) (defmacro define-mod-operations (divisor &optional (package #+sbcl (sb-int:sane-package) #-sbcl *package*)) (let ((mod* (intern "MOD*" package)) (mod+ (intern "MOD+" package)) (mod- (intern "MOD-" package)) (incfmod (intern "INCFMOD" package)) (decfmod (intern "DECFMOD" package)) (mulfmod (intern "MULFMOD" package))) `(progn (defun ,mod* (&rest args) (cond ((cdr args) (reduce (lambda (x y) (mod (* x y) ,divisor)) args)) (args (mod (car args) ,divisor)) (t 1))) (defun ,mod+ (&rest args) (cond ((cdr args) (reduce (lambda (x y) (mod (+ x y) ,divisor)) args)) (args (mod (car args) ,divisor)) (t 0))) (defun ,mod- (&rest args) (if (cdr args) (reduce (lambda (x y) (mod (- x y) ,divisor)) args) (mod (- (car args)) ,divisor))) #+sbcl (eval-when (:compile-toplevel :load-toplevel :execute) (locally (declare (sb-ext:muffle-conditions warning)) (sb-c:define-source-transform ,mod* (&rest args) (case (length args) (0 1) (1 `(mod ,(car args) ,',divisor)) (otherwise (reduce (lambda (x y) `(mod (* ,x ,y) ,',divisor)) args)))) (sb-c:define-source-transform ,mod+ (&rest args) (case (length args) (0 0) (1 `(mod ,(car args) ,',divisor)) (otherwise (reduce (lambda (x y) `(mod (+ ,x ,y) ,',divisor)) args)))) (sb-c:define-source-transform ,mod- (&rest args) (case (length args) (0 (values nil t)) (1 `(mod (- ,(car args)) ,',divisor)) (otherwise (reduce (lambda (x y) `(mod (- ,x ,y) ,',divisor)) args)))))) (define-modify-macro ,incfmod (delta) (lambda (x y) (mod (+ x y) ,divisor))) (define-modify-macro ,decfmod (delta) (lambda (x y) (mod (- x y) ,divisor))) (define-modify-macro ,mulfmod (multiplier) (lambda (x y) (mod (* x y) ,divisor)))))) (define-mod-operations cl-user::+mod+ :cl-user) (defpackage :cp/read-fixnum (:use :cl) (:export #:read-fixnum)) (in-package :cp/read-fixnum) (declaim (ftype (function * (values fixnum &optional)) read-fixnum)) (defun read-fixnum (&optional (in *standard-input*)) "NOTE: cannot read -2^62" (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* ((minus nil) (result (loop (let ((byte (%read-byte))) (cond ((<= 48 byte 57) (return (- byte 48))) ((zerop byte) ; #\Nul (error "Read EOF or #\Nul.")) ((= byte #.(char-code #\-)) (setq minus t))))))) (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 (if minus (- result) result)))))))) ;;; ;;; Implicit treap ;;; (treap with implicit key) ;;; ;; TODO: abstraction (defpackage :cp/implicit-treap (:use :cl) (:export #:itreap #:itreap-p #:itreap-count #:itreap-accumulator #:make-itreap #:invalid-itreap-index-error #:itreap-ref #:itreap-split #:itreap-merge #:itreap-insert #:itreap-delete #:itreap-push #:itreap-pop #:itreap-map #:do-itreap #:itreap-fold #:itreap-fold-bisect #:itreap-fold-bisect-from-end #:itreap-update #:itreap-reverse #:itreap-bisect-left #:itreap-bisect-right #:itreap-insort)) (in-package :cp/implicit-treap) ;; Note: ;; - An empty treap is NIL. (declaim (inline op)) (defun op (a b) "Is a binary operator comprising a monoid." (declare ((unsigned-byte 31) a b)) (mod (+ a b) cl-user::+mod+)) (defconstant +op-identity+ 0 "identity element w.r.t. OP") (defconstant +updater-identity+ 0 "identity element w.r.t. UPDATER-OP") (defstruct (itreap (:constructor %make-itreap (value priority &key left right (count 1) (accumulator value))) (:copier nil) (:conc-name %itreap-)) (value +op-identity+ :type (unsigned-byte 31)) (accumulator +op-identity+ :type (unsigned-byte 31)) (priority 0 :type (integer 0 #.most-positive-fixnum)) (count 1 :type (mod #.most-positive-fixnum)) ; size of (sub)treap (left nil :type (or null itreap)) (right nil :type (or null itreap))) (declaim (inline itreap-count)) (defun itreap-count (itreap) "Returns the number of the elements of ITREAP." (declare ((or null itreap) itreap)) (if itreap (%itreap-count itreap) 0)) (declaim (inline itreap-accumulator)) (defun itreap-accumulator (itreap) "Returns the sum (w.r.t. OP) of the whole ITREAP: ITREAP[0]+ITREAP[1]+...+ITREAP[SIZE-1]." (declare ((or null itreap) itreap)) (if itreap (%itreap-accumulator itreap) +op-identity+)) (declaim (inline update-count)) (defun update-count (itreap) (declare (itreap itreap)) (setf (%itreap-count itreap) (+ 1 (itreap-count (%itreap-left itreap)) (itreap-count (%itreap-right itreap))))) (declaim (inline update-accumulator)) (defun update-accumulator (itreap) (declare (itreap itreap)) (setf (%itreap-accumulator itreap) (if (%itreap-left itreap) (if (%itreap-right itreap) (let ((mid (op (%itreap-accumulator (%itreap-left itreap)) (%itreap-value itreap)))) (op mid (%itreap-accumulator (%itreap-right itreap)))) (op (%itreap-accumulator (%itreap-left itreap)) (%itreap-value itreap))) (if (%itreap-right itreap) (op (%itreap-value itreap) (%itreap-accumulator (%itreap-right itreap))) (%itreap-value itreap))))) (declaim (inline force-up)) (defun force-up (itreap) "Propagates up the information from children." (declare (itreap itreap)) (update-count itreap) (update-accumulator itreap)) (defun %heapify (node) "Makes it max-heap w.r.t. priorities by swapping the priorities of the whole treap." (declare (optimize (speed 3) (safety 0))) (when node (let ((high-priority-node node)) (when (and (%itreap-left node) (> (%itreap-priority (%itreap-left node)) (%itreap-priority high-priority-node))) (setq high-priority-node (%itreap-left node))) (when (and (%itreap-right node) (> (%itreap-priority (%itreap-right node)) (%itreap-priority high-priority-node))) (setq high-priority-node (%itreap-right node))) (unless (eql high-priority-node node) (rotatef (%itreap-priority high-priority-node) (%itreap-priority node)) (%heapify high-priority-node))))) (declaim (inline make-itreap)) (defun make-itreap (size &key initial-contents) "Makes a treap of SIZE in O(SIZE) time. Its values are filled with the identity element unless INITIAL-CONTENTS are supplied." (declare ((or null vector) initial-contents)) (labels ((build (l r) (declare ((integer 0 #.most-positive-fixnum) l r)) (if (= l r) nil (let* ((mid (ash (+ l r) -1)) (node (%make-itreap (if initial-contents (aref initial-contents mid) +op-identity+) (random most-positive-fixnum)))) (setf (%itreap-left node) (build l mid)) (setf (%itreap-right node) (build (+ mid 1) r)) (%heapify node) (force-up node) node)))) (build 0 size))) (define-condition invalid-itreap-index-error (type-error) ((itreap :initarg :itreap :reader invalid-itreap-index-error-itreap) (index :initarg :index :reader invalid-itreap-index-error-index)) (:report (lambda (condition stream) (let ((index (invalid-itreap-index-error-index condition))) (if (consp index) (format stream "Invalid range [~W, ~W) for itreap ~W." (car index) (cdr index) (invalid-itreap-index-error-itreap condition)) (format stream "Invalid index ~W for itreap ~W." index (invalid-itreap-index-error-itreap condition))))))) (defun itreap-split (itreap index) "Destructively splits ITREAP at INDEX and returns two treaps (in ascending order)." (declare (optimize (speed 3)) ((integer 0 #.most-positive-fixnum) index)) (unless (<= index (itreap-count itreap)) (error 'invalid-itreap-index-error :index index :itreap itreap)) (labels ((recur (itreap ikey) (unless itreap (return-from itreap-split (values nil nil))) (let ((left-count (itreap-count (%itreap-left itreap)))) (if (<= ikey left-count) (multiple-value-bind (left right) (itreap-split (%itreap-left itreap) ikey) (setf (%itreap-left itreap) right) (force-up itreap) (values left itreap)) (multiple-value-bind (left right) (itreap-split (%itreap-right itreap) (- ikey left-count 1)) (setf (%itreap-right itreap) left) (force-up itreap) (values itreap right)))))) (recur itreap index))) (defun itreap-merge (left right) "Destructively concatenates two ITREAPs. Note that this `merge' is different from CL:MERGE and rather close to CL:CONCATENATE." (declare (optimize (speed 3)) ((or null itreap) left right)) (cond ((null left) (when right (force-up right)) right) ((null right) (when left (force-up left)) left) (t (if (> (%itreap-priority left) (%itreap-priority right)) (progn (setf (%itreap-right left) (itreap-merge (%itreap-right left) right)) (force-up left) left) (progn (setf (%itreap-left right) (itreap-merge left (%itreap-left right))) (force-up right) right))))) (defun itreap-insert (itreap index obj) "Destructively inserts OBJ into ITREAP at INDEX and returns the resultant treap. You cannot rely on the side effect. Use the returned value." (declare (optimize (speed 3)) ((or null itreap) itreap) ((integer 0 #.most-positive-fixnum) index)) (unless (<= index (itreap-count itreap)) (error 'invalid-itreap-index-error :itreap itreap :index index)) (let ((node (%make-itreap obj (random most-positive-fixnum)))) (labels ((recur (itreap ikey) (declare ((integer 0 #.most-positive-fixnum) ikey)) (unless itreap (return-from recur node)) (if (> (%itreap-priority node) (%itreap-priority itreap)) (progn (setf (values (%itreap-left node) (%itreap-right node)) (itreap-split itreap ikey)) (force-up node) node) (let ((left-count (itreap-count (%itreap-left itreap)))) (if (<= ikey left-count) (setf (%itreap-left itreap) (recur (%itreap-left itreap) ikey)) (setf (%itreap-right itreap) (recur (%itreap-right itreap) (- ikey left-count 1)))) (force-up itreap) itreap)))) (recur itreap index)))) (defun itreap-delete (itreap index) "Destructively deletes the object at INDEX in ITREAP. You cannot rely on the side effect. Use the returned value." (declare (optimize (speed 3)) ((integer 0 #.most-positive-fixnum) index)) (unless (< index (itreap-count itreap)) (error 'invalid-itreap-index-error :itreap itreap :index index)) (labels ((recur (itreap ikey) (declare ((integer 0 #.most-positive-fixnum) ikey)) (let ((left-count (itreap-count (%itreap-left itreap)))) (cond ((< ikey left-count) (setf (%itreap-left itreap) (recur (%itreap-left itreap) ikey)) (force-up itreap) itreap) ((> ikey left-count) (setf (%itreap-right itreap) (recur (%itreap-right itreap) (- ikey left-count 1))) (force-up itreap) itreap) (t (itreap-merge (%itreap-left itreap) (%itreap-right itreap))))))) (recur itreap index))) (defmacro itreap-push (obj itreap pos) "Pushes OBJ to ITREAP at POS." `(setf ,itreap (itreap-insert ,itreap ,pos ,obj))) (defmacro itreap-pop (itreap pos) "Returns the object at POS and deletes it." (let ((p (gensym))) `(let ((,p ,pos)) (prog1 (itreap-ref ,itreap ,p) (setf ,itreap (itreap-delete ,itreap ,p)))))) (declaim (inline itreap-map)) (defun itreap-map (function itreap) "Successively applies FUNCTION to ITREAP[0], ..., ITREAP[SIZE-1]." (declare (function function)) (labels ((recur (node) (when node (recur (%itreap-left node)) (funcall function (%itreap-value node)) (recur (%itreap-right node)) (force-up node)))) (recur itreap))) (defmethod print-object ((object itreap) stream) (print-unreadable-object (object stream :type t) (let ((init t)) (itreap-map (lambda (x) (if init (setq init nil) (write-char #\ stream)) (write x :stream stream)) object)))) (defmacro do-itreap ((var itreap &optional result) &body body) "Successively binds ITREAP[0], ..., ITREAP[SIZE-1] to VAR and executes BODY each time." `(block nil (itreap-map (lambda (,var) ,@body) ,itreap) ,result)) (defun itreap (&rest args) ;; NOTE: This function takes O(nlog(n)) time. Use MAKE-ITREAP for efficiency. (labels ((recur (list position itreap) (declare ((integer 0 #.most-positive-fixnum) position)) (if (null list) itreap (recur (cdr list) (1+ position) (itreap-insert itreap position (car list)))))) (recur args 0 nil))) (declaim (inline itreap-ref)) (defun itreap-ref (itreap index) "Returns the element ITREAP[INDEX]." (declare ((integer 0 #.most-positive-fixnum) index)) (unless (< index (itreap-count itreap)) (error 'invalid-itreap-index-error :itreap itreap :index index)) (labels ((%ref (itreap index) (declare ((integer 0 #.most-positive-fixnum) index)) (prog1 (let ((left-count (itreap-count (%itreap-left itreap)))) (cond ((< index left-count) (%ref (%itreap-left itreap) index)) ((> index left-count) (%ref (%itreap-right itreap) (- index left-count 1))) (t (%itreap-value itreap)))) (force-up itreap)))) (%ref itreap index))) (declaim (inline (setf itreap-ref))) (defun (setf itreap-ref) (new-value itreap index) "Sets ITREAP[INDEX] to the given value." (declare ((integer 0 #.most-positive-fixnum) index)) (unless (< index (itreap-count itreap)) (error 'invalid-itreap-index-error :itreap itreap :index index)) (labels ((%set (itreap index) (declare ((integer 0 #.most-positive-fixnum) index)) (prog1 (let ((left-count (itreap-count (%itreap-left itreap)))) (cond ((< index left-count) (%set (%itreap-left itreap) index)) ((> index left-count) (%set (%itreap-right itreap) (- index left-count 1))) (t (setf (%itreap-value itreap) new-value)))) (force-up itreap)))) (%set itreap index) new-value)) (declaim (inline itreap-fold)) (defun itreap-fold (itreap l r) "Returns the `sum' (w.r.t. OP) of the range ITREAP[L, R)." (declare ((integer 0 #.most-positive-fixnum) l r)) (unless (<= l r (itreap-count itreap)) (error 'invalid-itreap-index-error :itreap itreap :index (cons l r))) (labels ((recur (itreap l r) (declare ((integer 0 #.most-positive-fixnum) l r)) (unless itreap (return-from recur +op-identity+)) (prog1 (if (and (zerop l) (= r (%itreap-count itreap))) (itreap-accumulator itreap) (let ((left-count (itreap-count (%itreap-left itreap)))) (if (<= l left-count) (if (< left-count r) ;; LEFT-COUNT is in [L, R) (op (op (recur (%itreap-left itreap) l (min r left-count)) (%itreap-value itreap)) (recur (%itreap-right itreap) 0 (- r left-count 1))) ;; LEFT-COUNT is in [R, END) (recur (%itreap-left itreap) l (min r left-count))) ;; LEFT-COUNT is in [0, L) (recur (%itreap-right itreap) (- l left-count 1) (- r left-count 1))))) (force-up itreap)))) (recur itreap l r))) ;; FIXME: might be problematic when two priorities collide and START is not ;; zero. (It will be negligible from the viewpoint of probability, however.) (declaim (inline itreap-fold-bisect)) (defun itreap-fold-bisect (itreap test &optional (start 0)) "Returns the largest index that satisfies (FUNCALL TEST (OP ITREAP[START] ITREAP[START+1] ... ITREAP[index-1])). Note: - (FUNCALL TEST +OP-IDENTITY+) must be true. - TEST must be monotone in the target range. " (declare ((integer 0 #.most-positive-fixnum) start)) (assert (funcall test +op-identity+)) (multiple-value-bind (itreap-prefix itreap) (if (zerop start) (values nil itreap) (itreap-split itreap start)) (labels ((recur (itreap offset prev-sum) (declare ((integer 0 #.most-positive-fixnum) offset) #+sbcl (values (integer 0 #.most-positive-fixnum))) (unless itreap (return-from recur offset)) (let ((sum prev-sum)) (prog1 (cond ((not (funcall test (setq sum (op sum (itreap-accumulator (%itreap-left itreap)))))) (recur (%itreap-left itreap) offset prev-sum)) ((not (funcall test (setq sum (op sum (%itreap-value itreap))))) (+ offset (itreap-count (%itreap-left itreap)))) (t (recur (%itreap-right itreap) (+ offset (itreap-count (%itreap-left itreap)) 1) sum))) (force-up itreap))))) (prog1 (+ start (recur itreap 0 +op-identity+)) (itreap-merge itreap-prefix itreap))))) (declaim (inline itreap-fold-bisect-from-end)) (defun itreap-fold-bisect-from-end (itreap test &optional end) "Returns the smallest index that satisfies (FUNCALL TEST (OP ITREAP[index] ITREAP[index+1] ... ITREAP[END-1])). Note: - (FUNCALL TEST +OP-IDENTITY+) must be true. - TEST must be monotone in the target range. " (declare ((or null (integer 0 #.most-positive-fixnum)) end)) (assert (funcall test +op-identity+)) (multiple-value-bind (itreap itreap-suffix) (if end (itreap-split itreap end) (values itreap nil)) (labels ((recur (itreap offset prev-sum) (declare ((integer 0 #.most-positive-fixnum) offset) #+sbcl (values (integer 0 #.most-positive-fixnum))) (unless itreap (return-from recur offset)) (let ((sum prev-sum)) (prog1 (cond ((not (funcall test (setq sum (op (itreap-accumulator (%itreap-right itreap)) sum)))) (recur (%itreap-right itreap) offset prev-sum)) ((not (funcall test (setq sum (op (%itreap-value itreap) sum)))) (+ offset (itreap-count (%itreap-right itreap)))) (t (recur (%itreap-left itreap) (+ offset (itreap-count (%itreap-right itreap)) 1) sum))) (force-up itreap))))) (prog1 (- (or end (itreap-count itreap)) (recur itreap 0 +op-identity+)) (itreap-merge itreap itreap-suffix))))) ;;; ;;; Below are utilities for treap whose values are sorted w.r.t. some order ;;; (declaim (inline itreap-bisect-left) (ftype (function * (values (integer 0 #.most-positive-fixnum) &optional)) itreap-bisect-left)) (defun itreap-bisect-left (itreap value order &key (key #'identity)) "Takes a **sorted** treap and returns the smallest index that satisfies ITREAP[index] >= VALUE, where >= is the complement of ORDER. In other words, this function returns a leftmost index at which value can be inserted with keeping the order. Returns the size of ITREAP if ITREAP[length-1] < VALUE. The time complexity is O(log(n))." (labels ((recur (count itreap) (declare ((integer 0 #.most-positive-fixnum) count)) (cond ((null itreap) nil) ((funcall order (funcall key (%itreap-value itreap)) value) (recur count (%itreap-right itreap))) (t (let ((left-count (- count (itreap-count (%itreap-right itreap)) 1))) (or (recur left-count (%itreap-left itreap)) left-count)))))) (or (recur (itreap-count itreap) itreap) (itreap-count itreap)))) (declaim (inline itreap-bisect-right) (ftype (function * (values (integer 0 #.most-positive-fixnum) &optional)) itreap-bisect-right)) (defun itreap-bisect-right (itreap value order &key (key #'identity)) "Takes a **sorted** treap and returns the smallest index that satisfies VALUE < ITREAP[index], where < is ORDER. In other words, this function returns a rightmost index at which VALUE can be inserted with keeping the order. Returns the size of ITREAP if ITREAP[length-1] <= VALUE. The time complexity is O(log(n))." (labels ((recur (count itreap) (declare ((integer 0 #.most-positive-fixnum) count)) (cond ((null itreap) nil) ((funcall order value (funcall key (%itreap-value itreap))) (let ((left-count (- count (itreap-count (%itreap-right itreap)) 1))) (or (recur left-count (%itreap-left itreap)) left-count))) (t (recur count (%itreap-right itreap)))))) (or (recur (itreap-count itreap) itreap) (itreap-count itreap)))) (declaim (inline itreap-insort)) (defun itreap-insort (itreap obj order) "Does insertion to the sorted treap with keeping the order. You cannot rely on the side effect. Use the returned value." (let ((pos (itreap-bisect-left itreap obj order))) (itreap-insert itreap pos obj))) ;; BEGIN_USE_PACKAGE (eval-when (:compile-toplevel :load-toplevel :execute) (use-package :cp/mod-operations :cl-user)) (eval-when (:compile-toplevel :load-toplevel :execute) (use-package :cp/implicit-treap :cl-user)) (eval-when (:compile-toplevel :load-toplevel :execute) (use-package :cp/read-fixnum :cl-user)) (in-package :cl-user) ;;; ;;; Body ;;; (defun main () (let* ((n (read)) (as (make-array n :element-type 'uint31 :initial-element 0)) (rsums (make-array n :element-type 'uint31 :initial-element 0)) (lsums (make-array n :element-type 'uint31 :initial-element 0)) (rcounts (make-array n :element-type 'uint31 :initial-element 0)) (lcounts (make-array n :element-type 'uint31 :initial-element 0)) (res 0)) (dotimes (i n) (setf (aref as i) (read-fixnum))) (let (itreap) (loop for i from 0 below n for a = (aref as i) for pos = (itreap-bisect-left itreap a #'>) do (setf (aref lcounts i) pos (aref lsums i) (itreap-fold itreap 0 pos) itreap (itreap-insort itreap a #'>)) #>itreap)) (let (itreap) (loop for i from (- n 1) downto 0 for a = (aref as i) for pos = (itreap-bisect-left itreap a #'<) do (setf (aref rcounts i) pos (aref rsums i) (itreap-fold itreap 0 pos) itreap (itreap-insort itreap a #'<)))) (dbg rsums lsums rcounts lcounts) (dotimes (i n) (let ((a (aref as i))) (incfmod res (mod* (aref lcounts i) (aref rcounts i) a)) (incfmod res (mod* (aref lsums i) (aref rcounts i))) (incfmod res (mod* (aref rsums i) (aref lcounts i))))) (println res))) #-swank (main) ;;; ;;; Test and benchmark ;;; #+swank (progn (defparameter *lisp-file-pathname* (uiop:current-lisp-file-pathname)) (setq *default-pathname-defaults* (uiop:pathname-directory-pathname *lisp-file-pathname*)) (uiop:chdir *default-pathname-defaults*) (defparameter *dat-pathname* (uiop:merge-pathnames* "test.dat" *lisp-file-pathname*)) (defparameter *problem-url* "https://yukicoder.me/problems/no/1300")) #+swank (defun gen-dat () (uiop:with-output-file (out *dat-pathname* :if-exists :supersede) (format out ""))) #+swank (defun bench (&optional (out (make-broadcast-stream))) (time (run *dat-pathname* out))) #+(and sbcl (not swank)) (eval-when (:compile-toplevel) (when (or (> sb-c::*compiler-warning-count* 0) sb-c::*undefined-warnings*) (error "count: ~D, undefined warnings: ~A" sb-c::*compiler-warning-count* sb-c::*undefined-warnings*))) ;; To run: (5am:run! :sample) #+swank (5am:test :sample (5am:is (equal "6 " (run "3 3 2 1 " nil))) (5am:is (equal "15 " (run "4 4 2 3 1 " nil))) (5am:is (equal "69 " (run "10 3 1 4 1 5 9 2 6 5 3 " nil))))