Problem:
Score : 700 points

Problem Statement

Given are positive integers N and K.

Determine if the 3N integers K, K+1, ..., K+3N-1 can be partitioned into N triples (a_1,b_1,c_1), ..., (a_N,b_N,c_N) so that the condition below is satisfied. Any of the integers K, K+1, ..., K+3N-1 must appear in exactly one of those triples.

For every integer i from 1 to N, a_i + b_i \leq c_i holds.

If the answer is yes, construct one such partition.

Constraints

1 \leq N \leq 10^5

1 \leq K \leq 10^9

Input

Input is given from Standard Input in the following format:

N K

Output

If it is impossible to partition the integers satisfying the condition, print -1. If it is possible, print N triples in the following format:

a_1 b_1 c_1
:
a_N b_N c_N

Sample Input 1

1 1

Sample Output 1

1 2 3

Sample Input 2

3 3

Sample Output 2

-1

Solution in Common Lisp (SBCL 2.0.3) (judge verdict: Accepted)

(in-package :cl-user)
(eval-when (:compile-toplevel :load-toplevel :execute)
  (sb-int:defconstant-eqx opt
    #+swank '(optimize (speed 3) (safety 2))
    #-swank '(optimize (speed 3) (safety 0) (debug 0))
    #'equal)
  #+swank (ql:quickload '(:cl-debug-print :fiveam) :silent t)
  #-swank (set-dispatch-macro-character
           #\# #\> (lambda (s c p) (declare (ignore c p)) `(values ,(read s nil nil t)))))
#+swank (set-dispatch-macro-character #\# #\> #'cl-debug-print:debug-print-reader)

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

(defconstant +mod+ 1000000007)

(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* 'double-float))
    (prog1 (princ obj stream) (terpri stream))))

;; BEGIN_INSERTED_CONTENTS
(defpackage :cp/treap
  (:use :cl)
  (:export #:treap #:treap-count #:treap-find #:treap-bisect-left #:treap-bisect-right-1
           #:treap-split #:treap-insert #:treap-push #:treap-pop #:treap-delete #:treap-merge
           #:treap-map #:invalid-treap-index-error #:treap-first #:treap-last))
(in-package :cp/treap)

;; Not included in test script. Better to use ref-able-treap instead.

(defstruct (treap (:constructor %make-treap (key priority &optional left right))
                  (:copier nil)
                  (:predicate nil)
                  (:conc-name %treap-))
  key
  (priority 0 :type (integer 0 #.most-positive-fixnum))
  (left nil :type (or null treap))
  (right nil :type (or null treap)))

(declaim (inline treap-key))
(defun treap-key (treap)
  (and treap (%treap-key treap)))

(declaim (inline treap-find))
(defun treap-find (key treap &key (order #'<))
  "Searches the sub-treap of TREAP whose key satisfies (and (not (funcall order
key (%treap-key sub-treap))) (not (funcall order (%treap-key sub-treap) key))) and
returns KEY. Returns NIL if KEY is not contained."
  (declare (function order)
           ((or null treap) treap))
  (labels ((recur (treap)
             (cond ((null treap) nil)
                   ((funcall order key (%treap-key treap))
                    (recur (%treap-left treap)))
                   ((funcall order (%treap-key treap) key)
                    (recur (%treap-right treap)))
                   (t key))))
    (recur treap)))

(declaim (inline treap-split))
(defun treap-split (key treap &key (order #'<))
  "Destructively splits the TREAP with reference to KEY and returns two treaps,
the smaller sub-treap (< KEY) and the larger one (>= KEY)."
  (declare (function order)
           ((or null treap) treap))
  (labels ((recur (treap)
             (cond ((null treap)
                    (values nil nil))
                   ((funcall order (%treap-key treap) key)
                    (multiple-value-bind (left right)
                        (recur (%treap-right treap))
                      (setf (%treap-right treap) left)
                      (values treap right)))
                   (t
                    (multiple-value-bind (left right)
                        (recur (%treap-left treap))
                      (setf (%treap-left treap) right)
                      (values left treap))))))
    (recur treap)))

(declaim (inline treap-insert))
(defun treap-insert (key treap &key (order #'<))
  "Destructively inserts KEY into TREAP and returns the resultant treap. You
cannot rely on the side effect. Use the returned value.

The behavior is undefined when duplicate keys are inserted."
  (declare ((or null treap) treap)
           (function order))
  (labels ((recur (new-node treap)
             (declare (treap new-node))
             (cond ((null treap) new-node)
                   ((> (%treap-priority new-node) (%treap-priority treap))
                    (setf (values (%treap-left new-node) (%treap-right new-node))
                          (treap-split (%treap-key new-node) treap :order order))
                    new-node)
                   (t
                    (if (funcall order (%treap-key new-node) (%treap-key treap))
                        (setf (%treap-left treap)
                              (recur new-node (%treap-left treap)))
                        (setf (%treap-right treap)
                              (recur new-node (%treap-right treap))))
                    treap))))
    (recur (%make-treap key (random most-positive-fixnum)) treap)))

(defun treap-map (function treap)
  "Successively applies FUNCTION to each key of TREAP in the given
order. FUNCTION must take one argument."
  (declare (function function))
  (when treap
    (treap-map function (%treap-left treap))
    (funcall function (%treap-key treap))
    (treap-map function (%treap-right treap))))

(defmethod print-object ((object treap) stream)
  (print-unreadable-object (object stream :type t)
    (let ((init t))
      (treap-map (lambda (key)
                   (if init
                       (setf init nil)
                       (write-char #\  stream))
                   (write key :stream stream))
                 object))))

(declaim (ftype (function * (values (or null treap) &optional)) treap-merge))
(defun treap-merge (left right)
  "Destructively concatenates two treaps. Assumes that all keys of LEFT are
smaller (or larger, depending on the order) than those of RIGHT."
  (declare (optimize (speed 3))
           ((or null treap) left right))
  (cond ((null left) right)
        ((null right) left)
        ((> (%treap-priority left) (%treap-priority right))
         (setf (%treap-right left)
               (treap-merge (%treap-right left) right))
         left)
        (t
         (setf (%treap-left right)
               (treap-merge left (%treap-left right)))
         right)))

(declaim (inline treap-delete))
(defun treap-delete (key treap &key (order #'<))
  "Destructively deletes the KEY in TREAP and returns the resultant treap. You
cannot rely on the side effect. Use the returned value."
  (declare ((or null treap) treap)
           (function order))
  (labels ((recur (treap)
             (cond ((null treap) nil)
                   ((funcall order key (%treap-key treap))
                    (setf (%treap-left treap) (recur (%treap-left treap)))
                    treap)
                   ((funcall order (%treap-key treap) key)
                    (setf (%treap-right treap) (recur (%treap-right treap)))
                    treap)
                   (t
                    (treap-merge (%treap-left treap) (%treap-right treap))))))
    (recur treap)))

(defmacro treap-push (key treap order)
  "Pushes KEY to TREAP."
  `(setf ,treap (treap-insert ,key ,treap :order ,order)))

(defmacro treap-pop (key treap order)
  "Deletes KEY from TREAP."
  `(setf ,treap (treap-delete ,key ,treap :order ,order)))

(defun treap-first (treap)
  (declare (optimize (speed 3))
           (treap treap))
  (if (%treap-left treap)
      (treap-first (%treap-left treap))
      (%treap-key treap)))

(defun treap-last (treap)
  (declare (optimize (speed 3))
           (treap treap))
  (if (%treap-right treap)
      (treap-last (%treap-right treap))
      (%treap-key treap)))

(declaim (ftype (function * (values (integer 0 #.most-positive-fixnum) &optional)) treap-count))
(defun treap-count (treap)
  "Counts the number of elements in TREAP in O(n) time."
  (declare (optimize (speed 3))
           ((or null treap) treap))
  (labels ((recur (treap)
             (declare (optimize (safety 0)))
             (if (null treap)
                 0
                 (+ 1
                    (treap-count (%treap-left treap))
                    (treap-count (%treap-right treap))))))
    (recur treap)))

(declaim (inline treap-bisect-left))
(defun treap-bisect-left (treap key &key (order #'<))
  "Returns the smallest key equal to or larger than KEY. Returns NIL if KEY is
larger than any keys in TREAP."
  (declare ((or null treap) treap)
           (function order))
  (labels ((recur (treap)
             (unless treap (return-from recur nil))
             (if (funcall order (%treap-key treap) key)
                 (recur (%treap-right treap))
                 (or (recur (%treap-left treap))
                     treap))))
    (treap-key (recur treap))))

(declaim (inline treap-bisect-right-1))
(defun treap-bisect-right-1 (treap key &key (order #'<))
  "Returns the largest key equal to or smaller than KEY. Returns NIL if KEY is
smaller than any keys in TREAP."
  (declare ((or null treap) treap)
           (function order))
  (labels ((recur (treap)
             (cond ((null treap) nil)
                   ((funcall order key (%treap-key treap))
                    (recur (%treap-left treap)))
                   (t (or (recur (%treap-right treap))
                          treap)))))
    (treap-key (recur treap))))

;; (defun copy-treap (treap)
;;   "For development. Recursively copies the whole TREAP."
;;   (declare ((or null treap) treap))
;;   (if (null treap)
;;       nil
;;       (%make-treap (%treap-key treap)
;;                   (%treap-priority treap)
;;                   (copy-treap (%treap-left treap))
;;                   (copy-treap (%treap-right treap)))))

;; Test
;; (let ((treap1 (%make-treap 50 15))
;;       (treap2 (%make-treap 100 11)))
;;   (setf (%treap-left treap1) (%make-treap 30 5))
;;   (setf (%treap-left (%treap-left treap1)) (%make-treap 20 2))
;;   (setf (%treap-right (%treap-left treap1)) (%make-treap 40 4))
;;   (setf (%treap-right treap1) (%make-treap 70 10))
;;   (setf (%treap-right treap2) (%make-treap 200 3))
;;   (setf (%treap-left treap2) (%make-treap 99 5))
;;   ;; copy-treap
;;   (assert (equalp treap1 (copy-treap treap1)))
;;   (assert (not (eql treap1 (copy-treap treap1))))
;;   ;; split and merge
;;   (let ((treap (treap-merge (copy-treap treap1) (copy-treap treap2))))
;;     (multiple-value-bind (left right) (treap-split 80 (copy-treap treap))
;;       (assert (equalp treap (treap-merge left right)))))
;;   ;; find
;;   (assert (= 40 (treap-find 40 treap1)))
;;   (assert (null (treap-find 41 treap1)))
;;   ;; insert and delete
;;   (let ((inserted-treap1 (treap-insert 41 (copy-treap treap1))))
;;     (assert (= 41 (treap-find 41 inserted-treap1)))
;;     (let ((deleted-treap1 (treap-delete 41 inserted-treap1)))
;;       (assert (null (treap-find 41 deleted-treap1)))
;;       (assert (equalp treap1 deleted-treap1))
;;       (assert (equalp treap1 (treap-delete 41 deleted-treap1))))))

;; (multiple-value-bind (left right) (treap-split 5 (treap-insert 0 (treap-insert 10 (treap-insert 5 nil))))
;;   (assert (= 0 (%treap-key left)))
;;   (assert (null (%treap-left left)))
;;   (assert (null (%treap-right left)))
;;   (assert (or (typep (%treap-left right) 'treap)
;;               (typep (%treap-right right) 'treap))))


;; BEGIN_USE_PACKAGE
(eval-when (:compile-toplevel :load-toplevel :execute)
  (use-package :cp/treap :cl-user))
(in-package :cl-user)

;;;
;;; Body
;;;

;; cには後半1/3をあてるべき
(defun calc (x)
  (ash (* x (+ x 1)) -1))
(defun main ()
  (let* ((n (read))
         (k (read))
         (ab-sum (- (calc (+ k (* 2 n) -1))
                    (calc (+ k -1))))
         (c-sum (- (calc (+ k (* 3 n) -1))
                   (calc (+ k (* 2 n) -1))))
         (out (make-string-output-stream :element-type 'base-char))
         res-ab)
    (dbg ab-sum c-sum)
    (labels ((no () (println -1) (return-from main)))
      (when (> ab-sum c-sum) (no))
      (let* ((cstart (+ k (* 2 n)))
             (astart k)
             (bstart (+ k n)))
        (loop for a from astart
              for b downfrom (- cstart 1) by 2
              do (dbg a b)
              while (and (< a bstart) (>= b bstart))
              do (push (cons a b) res-ab)
              finally (loop for a2 from a
                            for b2 downfrom (- cstart 2) by 2
                            while (and (< a2 bstart) (>= b2 bstart))
                            do (push (cons a2 b2) res-ab)))
        (setq res-ab (sort res-ab #'< :key (lambda (cons) (+ (car cons) (cdr cons)))))
        (loop for (a . b) in res-ab
              for c from cstart
              unless (<= (+ a b) c)
              do (no)
              do (format out "~D ~D ~D~%" a b c)))
      (write-string (get-output-stream-string out)))))

#-swank (main)

;;;
;;; Test and benchmark
;;;

#+swank
(defun get-clipbrd ()
  (with-output-to-string (out)
    #+os-windows (run-program "powershell.exe" '("-Command" "Get-Clipboard") :output out :search t)
    #+os-unix (run-program "xsel" '("-b" "-o") :output out :search t)))

#+swank (defparameter *this-pathname* (uiop:current-lisp-file-pathname))
#+swank (defparameter *dat-pathname* (uiop:merge-pathnames* "test.dat" *this-pathname*))

#+swank
(defun run (&optional thing (out *standard-output*))
  "THING := null | string | symbol | pathname

null: run #'MAIN using the text on clipboard as input.
string: run #'MAIN using the string as input.
symbol: alias of FIVEAM:RUN!.
pathname: run #'MAIN using the text file as input."
  (let* ((*standard-output* (or out (make-string-output-stream)))
         (res (etypecase thing
                (null
                 (with-input-from-string (*standard-input* (delete #\Return (get-clipbrd)))
                   (main)))
                (string
                 (with-input-from-string (*standard-input* (delete #\Return thing))
                   (main)))
                (symbol (5am:run! thing))
                (pathname
                 (with-open-file (*standard-input* thing)
                   (main))))))
    (if out res (get-output-stream-string *standard-output*))))

#+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)))

#-swank
(eval-when (:compile-toplevel)
  (when (and (boundp 'sb-c::*compiler-warning-count*)
             (> sb-c::*compiler-warning-count* 0))
    (sb-ext:quit :unix-status 1)))

;; To run: (5am:run! :sample)
#+swank
(it.bese.fiveam:test :sample
  (5am:is
   (equal "1 2 3
"
          (run "1 1
" nil)))
  (5am:is
   (equal "-1
"
          (run "3 3
" nil))))