;; -*- coding: utf-8 -*-
(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)) (read s nil nil t))))
#+swank (cl-syntax:use-syntax cl-debug-print:debug-print-syntax)
#-swank (disable-debugger) ; for CS Academy

;; BEGIN_INSERTED_CONTENTS
(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)

(defun delete-adjacent-duplicates (seq &key (test #'eql))
  "Destructively deletes adjacent duplicates of SEQ: e.g. #(1 1 1 2 2 1 3) ->
#(1 2 1 3)"
  (declare #.OPT
           ((simple-array uint31 (*)) seq)
           (function test))
  (if (zerop (length seq))
         seq
         (let ((prev (aref seq 0))
               (end 1))
           (loop for pos from 1 below (length seq)
                 unless (funcall test prev (aref seq pos))
                 do (setf prev (aref seq pos)
                          (aref seq end) (aref seq pos)
                          end (+ 1 end)))
           ;; KLUDGE: Resorting to ADJUST-ARRAY is maybe substandard. 
           (adjust-array seq end))))

(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* ((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 #\-))
                                  (setf 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))))))))

;;;
;;; Treap with explicit key
;;; Virtually it works like std::map, std::multiset, or java.util.TreeMap.
;;;


;; Tips to use this structure as a multiset: Just define OP as (defun op (x y)
;; (+ x y)) and insert each element by (treap-ensure-key <treap> <key> 1
;; :if-exists #'1+) instead of TREAP-INSERT.

(declaim (inline op))
(defun op (x y)
  "Is the operator comprising a monoid"
  (declare (uint32 x y))
  (max x y))

(defconstant +op-identity+ 0
  "identity element w.r.t. OP")

(declaim (inline updater-op))
(defun updater-op (a b)
  "Is the operator to compute and update LAZY value."
  (declare (int32 a b))
  (+ a b))

(defconstant +updater-identity+ 0
  "identity element w.r.t. UPDATER-OP")

(declaim (inline modifier-op))
(defun modifier-op (a b)
  "Is the operator to update ACCUMULATOR based on LAZY value."
  (declare (int32 a b))
  (+ a b))

;; Treap with explicit key
(defstruct (treap (:constructor %make-treap (key value &key left right (accumulator value) lazy))
                  (:copier nil)
                  (:conc-name %treap-))
  (key 0 :type fixnum)
  (value +op-identity+ :type fixnum)
  (accumulator +op-identity+ :type fixnum)
  (lazy +updater-identity+ :type fixnum)
  (left nil :type (or null treap))
  (right nil :type (or null treap)))

(declaim (inline treap-accumulator))
(defun treap-accumulator (treap)
  (declare ((or null treap) treap))
  (if (null treap)
      +op-identity+
      (%treap-accumulator treap)))

(declaim (inline update-accumulator))
(defun update-accumulator (treap)
  (declare (treap treap))
  (setf (%treap-accumulator treap)
        (if (%treap-left treap)
            (if (%treap-right treap)
                (let ((mid-res (op (%treap-accumulator (%treap-left treap))
                                   (%treap-value treap))))
                  (op mid-res (%treap-accumulator (%treap-right treap))))
                (op (%treap-accumulator (%treap-left treap))
                    (%treap-value treap)))
            (if (%treap-right treap)
                (op (%treap-value treap)
                    (%treap-accumulator (%treap-right treap)))
                (%treap-value treap)))))

(declaim (inline force-up))
(defun force-up (treap)
  "Propagates up the information from children."
  (declare (treap treap))
  (update-accumulator treap))

(declaim (inline force-down))
(defun force-down (treap)
  "Propagates down the information to children."
  (declare (treap treap))
  (unless (eql +updater-identity+ (%treap-lazy treap))
    (when (%treap-left treap)
      (setf (%treap-lazy (%treap-left treap))
            (updater-op (%treap-lazy (%treap-left treap))
                        (%treap-lazy treap)))
      (setf (%treap-accumulator (%treap-left treap))
            (modifier-op (%treap-accumulator (%treap-left treap))
                         (%treap-lazy treap))))
    (when (%treap-right treap)
      (setf (%treap-lazy (%treap-right treap))
            (updater-op (%treap-lazy (%treap-right treap))
                        (%treap-lazy treap)))
      (setf (%treap-accumulator (%treap-right treap))
            (modifier-op (%treap-accumulator (%treap-right treap))
                         (%treap-lazy treap))))
    (setf (%treap-value treap)
          (modifier-op (%treap-value treap)
                       (%treap-lazy treap)))
    (setf (%treap-lazy treap) +updater-identity+)))

(defun treap-bisect-left (treap key)
  "Returns the smallest key equal to or larger than KEY and the assigned
value. Returns NIL if KEY is larger than any keys in TREAP."
  (declare #.OPT
           (fixnum key)
           ((or null treap) treap))
  (labels ((recur (treap)
             (unless treap (return-from recur nil))
             (force-down treap)
             (if (< (%treap-key treap) key)
                 (recur (%treap-right treap))
                 (or (recur (%treap-left treap))
                     treap))))
    (let ((result (recur treap)))
      (if result
          (values (%treap-key result) (%treap-value result))
          (values nil nil)))))

;; Reference: https://cp-algorithms.com/data_structures/treap.html
;; TODO: take a sorted list as the argument
(defun make-treap (sorted-vector)
  "Makes a treap using each key of the given SORTED-VECTOR in O(n). Note that
this function doesn't check if the SORTED-VECTOR is actually sorted w.r.t. your
intended order. The values are filled with the identity element."
  (declare #.OPT
           ((simple-array uint31 (*)) sorted-vector))
  (labels ((build (l r)
             (declare ((integer 0 #.most-positive-fixnum) l r))
             (if (= l r)
                 nil
                 (let* ((mid (ash (+ l r) -1))
                        (node (%make-treap (aref sorted-vector mid)
                                           +op-identity+)))
                   (setf (%treap-left node) (build l mid))
                   (setf (%treap-right node) (build (+ mid 1) r))
                   node))))
    (build 0 (length sorted-vector))))

(defconstant +pos-inf+ most-positive-fixnum)
(defconstant +neg-inf+ most-negative-fixnum)

(defun treap-query (treap &key left right)
  "Queries the sum of the half-open interval specified by the keys: [LEFT,
RIGHT). If LEFT [RIGHT] is not given, it is assumed to be -inf [+inf]."
  (declare #.OPT)
  (setq left (or left +neg-inf+)
        right (or right +pos-inf+))
  (labels ((recur (treap l r)
             (declare (fixnum l r))
             (unless treap
               (return-from recur +op-identity+))
             (force-down treap)
             (prog1
                 (if (and (= l +neg-inf+) (= r +pos-inf+))
                     (%treap-accumulator treap)
                     (let ((key (%treap-key treap)))
                       (if (<= l key)
                           (if (< key r)
                               (op (op (recur (%treap-left treap) l +pos-inf+)
                                       (%treap-value treap))
                                   (recur (%treap-right treap) +neg-inf+ r))
                               (recur (%treap-left treap) l r))
                           (recur (%treap-right treap) l r))))
               (force-up treap))))
    (recur treap left right)))

(defun treap-update (treap x left right)
  "Updates TREAP[KEY] := (OP TREAP[KEY] X) for all KEY in [l, r)"
  (declare #.OPT
           (fixnum left right))
  (assert (not (< right left)))
  (labels ((recur (treap l r)
             (declare (fixnum l r))
             (when treap
               (if (and (= l +neg-inf+) (= r +pos-inf+))
                   (progn
                     (setf (%treap-lazy treap)
                           (updater-op (%treap-lazy treap) x))
                     (force-down treap))
                   (let ((key (%treap-key treap)))
                     (force-down treap)
                     (if (<= l key)
                         (if (< key r)
                             (progn
                               (recur (%treap-left treap) l +pos-inf+)
                               (setf (%treap-value treap)
                                     (modifier-op (%treap-value treap) x))
                               (recur (%treap-right treap) +neg-inf+ r))
                             (recur (%treap-left treap) l r))
                         (recur (%treap-right treap) l r))))
               (force-up treap))))
    (recur treap left right)))

(defun treap-range-bisect (treap value)
  (declare #.OPT
           (fixnum value))
  (labels
      ((recur (treap prev-sum)
         (declare (fixnum prev-sum))
         (unless treap
           (return-from recur +pos-inf+))
         (force-down treap)
         (let ((sum prev-sum))
           (prog1
               (cond ((>= (setq sum (op sum (treap-accumulator (%treap-left treap))))
                          value)
                      (if (%treap-left treap)
                          (recur (%treap-left treap) prev-sum)
                          (%treap-key treap)))
                     ((>= (setq sum (op sum (%treap-value treap)))
                          value)
                      (%treap-key treap))
                     (t
                      (recur (%treap-right treap) sum)))
             (force-up treap)))))
    (recur treap +op-identity+)))

(defun treap-range-bisect-from-end (treap value)
  (declare #.OPT
           (fixnum value))
  (labels
      ((recur (treap prev-sum)
         (declare (fixnum prev-sum))
         (unless treap
           (return-from recur +neg-inf+))
         (force-down treap)
         (let ((sum prev-sum))
           (prog1
               (cond ((>= (setq sum (op (treap-accumulator (%treap-right treap)) sum))
                          value)
                      (if (%treap-right treap)
                          (recur (%treap-right treap) prev-sum)
                          (%treap-key treap)))
                     ((>= (setq sum (op (%treap-value treap) sum))
                          value)
                      (%treap-key treap))
                     (t
                      (recur (%treap-left treap) sum)))
             (force-up treap)))))
    (recur treap +op-identity+)))

(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))))

(defconstant +mod+ 1000000007)

;;;
;;; Body
;;;

(defun solve (n ls rs ords seq)
  (declare #.OPT
           (uint31 n)
           ((simple-array uint31 (*)) ls rs seq ords))
  (let ((inf (reduce #'max seq))
        (treap1 (make-treap seq))
        (treap2 (make-treap seq))
        (res 0))
    (declare (uint32 inf res))
    (dotimes (i n)
      (let ((l (aref ls i))
            (r (aref rs i)))
        (treap-update treap2 1 l r)))
    (dotimes (i n)
      (let* ((ord (aref ords i))
             (required1 i)
             (required2 (- n i))
             (l (aref ls ord))
             (r (aref rs ord))
             (max1 (treap-query treap1))
             (max2 (treap-query treap2)))
        (declare (uint32 required1 required2 max1 max2))
        (unless (zerop i)
          (when (and (= required1 max1) (= required2 max2))
            (let* ((max1l (treap-range-bisect treap1 max1))
                   (max1r (treap-bisect-left treap1 (+ 1 (treap-range-bisect-from-end treap1 max1))))
                   (max2l (treap-range-bisect treap2 max2))
                   (max2r (treap-bisect-left treap2 (+ 1 (treap-range-bisect-from-end treap2 max2))))
                   (new-score (+ (- max1r max1l) (- max2r max2l))))
              (declare (uint32 max1l max1r max2l max2r))
              (setq res (max res new-score)))))
        (treap-update treap1 1 l r)
        (treap-update treap2 -1 l r)))
    res))

(defun main ()
  (declare #.OPT
           (inline sort))
  (let* ((n (read))
         (ls (make-array n :element-type 'uint31))
         (rs (make-array n :element-type 'uint31))
         (ords (make-array n :element-type 'uint31))
         (seq (make-array (+ n n) :element-type 'uint31)))
    (dotimes (i n)
      (let ((l (- (read-fixnum) 1))
            (r (read-fixnum)))
        (setf (aref ls i) l
              (aref rs i) r
              (aref ords i) i
              (aref seq i) l
              (aref seq (+ i n)) r)))
    (setq seq (sort seq #'<)
          ords (sort ords (lambda (x y) (< (aref rs x) (aref rs y)))))
    (setq seq (delete-adjacent-duplicates seq))
    (let ((cand (solve n ls rs ords seq)))
      (let ((idx 0)
            (l 0)
            (r 1000000000))
        (declare (uint32 idx l r))
        (dotimes (i n)
          (when (>= (- (aref rs i) (aref ls i))
                    (- (aref rs idx) (aref ls idx)))
            (setq idx i)))
        (dotimes (i n)
          (unless (= idx i)
            (setq l (max l (aref ls i))
                  r (min r (aref rs i)))))
        (let ((cand2 (+ (- (aref rs idx) (aref ls idx))
                        (max 0 (- r l)))))
          (println (max cand cand2)))))))

#-swank (main)

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

#+swank
(defun io-equal (in-string out-string &key (function #'main) (test #'equal))
  "Passes IN-STRING to *STANDARD-INPUT*, executes FUNCTION, and returns true if
the string output to *STANDARD-OUTPUT* is equal to OUT-STRING."
  (labels ((ensure-last-lf (s)
             (if (eql (uiop:last-char s) #\Linefeed)
                 s
                 (uiop:strcat s uiop:+lf+))))
    (funcall test
             (ensure-last-lf out-string)
             (with-output-to-string (out)
               (let ((*standard-output* out))
                 (with-input-from-string (*standard-input* (ensure-last-lf in-string))
                   (funcall function)))))))

#+swank
(defun get-clipbrd ()
  (with-output-to-string (out)
    (run-program "C:/msys64/usr/bin/cat.exe" '("/dev/clipboard") :output out)))

#+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* out))
    (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))))))

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

;; To run: (5am:run! :sample)
#+swank
(it.bese.fiveam:test :sample
  (it.bese.fiveam:is
   (common-lisp-user::io-equal "4
4 7
1 4
5 8
2 5
"
    "6
"))
  (it.bese.fiveam:is
   (common-lisp-user::io-equal "4
1 20
2 19
3 18
4 17
"
    "34
"))
  (it.bese.fiveam:is
   (common-lisp-user::io-equal "10
457835016 996058008
456475528 529149798
455108441 512701454
455817105 523506955
457368248 814532746
455073228 459494089
456651538 774276744
457667152 974637457
457293701 800549465
456580262 636471526
"
    "540049931
")))


Measured memory_bytes: 70376