using System; using System.Collections.Generic; using System.Linq; class Program { static string InputPattern = "InputX"; static List GetInputList() { var WillReturn = new List(); if (InputPattern == "Input1") { WillReturn.Add("10 3"); WillReturn.Add("0 1"); WillReturn.Add("6 8"); WillReturn.Add("2 7"); } else if (InputPattern == "Input2") { WillReturn.Add("10 4"); WillReturn.Add("3 7"); WillReturn.Add("3 5"); WillReturn.Add("1 1"); WillReturn.Add("4 9"); } else if (InputPattern == "Input3") { WillReturn.Add("1000000000000000000 2"); WillReturn.Add("0 999999999999999999"); WillReturn.Add("0 999999999999999999"); } else { string wkStr; while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr); } return WillReturn; } static long[] GetSplitArr(string pStr) { return (pStr == "" ? new string[0] : pStr.Split(' ')).Select(pX => long.Parse(pX)).ToArray(); } static void Main() { List InputList = GetInputList(); long[] wkArr = { }; Action SplitAct = (pStr) => wkArr = GetSplitArr(pStr); var InsIntervalSet = new IntervalSet(); foreach (string EachStr in InputList.Skip(1)) { SplitAct(EachStr); long L = wkArr[0]; long R = wkArr[1]; InsIntervalSet.AddInterval(L, R); Console.WriteLine(InsIntervalSet.mMaxLen); } var wkList = InsIntervalSet.GetIntervalInfoList(); } } // 区間をsetで管理するテク #region IntervalSet // IntervalSetクラス internal class IntervalSet { internal struct IntervalInfoDef { internal long IntervalSta; internal long IntervalEnd; } internal long mMaxLen = 0; // 区間StaのAVL木 private AVL_Set_MultiSet mIntervalStaSet; // 区間End[区間Sta]なDict private Dictionary mIntervalEndDict; // コンストラクタ internal IntervalSet() { mIntervalStaSet = new AVL_Set_MultiSet(); mIntervalStaSet.IsMultiSet = true; mIntervalEndDict = new Dictionary(); } // 区間を追加 internal void AddInterval(long pSta, long pEnd) { // どの区間ともOverlapしてない場合 if (IsOverlapInterval(pSta, pEnd) == false) { mIntervalStaSet.Add(pSta); mIntervalEndDict[pSta] = pEnd; mMaxLen = Math.Max(mMaxLen, pEnd - pSta + 1); return; } // Overlapの上限 long AVLIndEnd = mIntervalStaSet.LowerOrEqual_Max(pEnd); var WillRemoveIndList = new List(); var WillRemoveStaList = new List(); long MergedIntervalSta = pSta; long MergedIntervalEnd = pEnd; for (long I = AVLIndEnd; 0 <= I; I--) { long CurrIntervalSta = mIntervalStaSet[I]; long CurrIntervalEnd = mIntervalEndDict[CurrIntervalSta]; if (IsOverlap_2_Interval( CurrIntervalSta, CurrIntervalEnd, MergedIntervalSta, MergedIntervalEnd)) { MergedIntervalSta = Math.Min(MergedIntervalSta, CurrIntervalSta); MergedIntervalEnd = Math.Max(MergedIntervalEnd, CurrIntervalEnd); WillRemoveIndList.Add(I); WillRemoveStaList.Add(CurrIntervalSta); } else break; } // 降順にRemove WillRemoveIndList.ForEach(pX => mIntervalStaSet.RemoveAt(pX)); WillRemoveStaList.ForEach(pX => mIntervalEndDict.Remove(pX)); // マージした区間を追加 mIntervalStaSet.Add(MergedIntervalSta); mIntervalEndDict[MergedIntervalSta] = MergedIntervalEnd; mMaxLen = Math.Max(mMaxLen, MergedIntervalEnd - MergedIntervalSta + 1); } // Intervalの大小チェック private void IntervalCheck(long pSta, long pEnd) { if (pSta > pEnd) throw new Exception("pSta > pEnd"); } // 引数の点を含む区間の存在判定 internal bool IsOverlapPoint(long pPoint) { return IsOverlapInterval(pPoint, pPoint); } // 引数の区間とOverlapする区間の存在判定 internal bool IsOverlapInterval(long pSta, long pEnd) { IntervalCheck(pSta, pEnd); long AVLInd = mIntervalStaSet.LowerOrEqual_Max(pEnd); if (mIntervalStaSet.IsValidInd(AVLInd) == false) { return false; } long KouhoSta = mIntervalStaSet[AVLInd]; long KouhoEnd = mIntervalEndDict[KouhoSta]; return IsOverlap_2_Interval(pSta, pEnd, KouhoSta, KouhoEnd); } // 区間2つを引数とし、Overlap有無を返す private bool IsOverlap_2_Interval(long pSta1, long pEnd1, long pSta2, long pEnd2) { return pSta1 - 1 <= pEnd2 && pSta2 - 1 <= pEnd1; } // 区間の配列を返す internal List GetIntervalInfoList() { List IntervalInfoList = new List(); long[] IntervalStaArr = mIntervalStaSet.Items; foreach (long EachIntervalSta in IntervalStaArr) { IntervalInfoDef WillAdd; WillAdd.IntervalSta = EachIntervalSta; WillAdd.IntervalEnd = mIntervalEndDict[EachIntervalSta]; IntervalInfoList.Add(WillAdd); } return IntervalInfoList; } } #endregion #region AVL_Set_MultiSet /// /// 要素の追加、削除、検索、取得が可能な集合を表します. /// /// 優先度付きキュー内の要素の型を指定します. /// 内部的にはAVL木によって実装されています. internal class AVL_Set_MultiSet { Node root; readonly IComparer comparer; readonly Node nil; /// /// 多重集合かどうかを表します. /// internal bool IsMultiSet { get; set; } internal AVL_Set_MultiSet(IComparer comparer) { nil = new Node(default(T)); root = nil; this.comparer = comparer; } internal AVL_Set_MultiSet() : this(Comparer.Default) { } /// /// 要素をコレクションに追加します. /// /// この操作は計算量 O(log N) で実行されます. internal bool Add(T v) { return insert(ref root, v); } /// /// v が存在するならコレクションから削除します. /// /// この操作は計算量 O(log N) で実行されます. internal bool Remove(T v) { return remove(ref root, v); } /// /// 0-indexed で index 番目の要素をコレクションから取得します. /// /// この操作は計算量 O(log N) で実行されます. internal T this[long index] { get { return find(root, index); } } internal long Count { get { return root.Count; } } internal void RemoveAt(long k) { if (k < 0 || k >= root.Count) throw new ArgumentOutOfRangeException(); removeAt(ref root, k); } /// /// このコレクションに含まれる要素を昇順に並べて返します. /// /// この操作は計算量 O(N) で実行されます. internal T[] Items { get { T[] ret = new T[root.Count]; long k = 0; walk(root, ret, ref k); return ret; } } private void walk(Node t, T[] a, ref long k) { if (t.Count == 0) return; walk(t.lst, a, ref k); a[k++] = t.Key; walk(t.rst, a, ref k); } private bool insert(ref Node t, T key) { if (t.Count == 0) { t = new Node(key); t.lst = t.rst = nil; t.Update(); return true; } int cmp = comparer.Compare(t.Key, key); bool res; if (cmp > 0) res = insert(ref t.lst, key); else if (cmp == 0) { if (IsMultiSet) res = insert(ref t.lst, key); else return false; } else res = insert(ref t.rst, key); balance(ref t); return res; } private bool remove(ref Node t, T key) { if (t.Count == 0) return false; int cmp = comparer.Compare(key, t.Key); bool ret; if (cmp < 0) ret = remove(ref t.lst, key); else if (cmp > 0) ret = remove(ref t.rst, key); else { ret = true; var k = t.lst.Count; if (k == 0) { t = t.rst; return true; } if (t.rst.Count == 0) { t = t.lst; return true; } t.Key = find(t.lst, k - 1); removeAt(ref t.lst, k - 1); } balance(ref t); return ret; } private void removeAt(ref Node t, long k) { long cnt = t.lst.Count; if (cnt < k) removeAt(ref t.rst, k - cnt - 1); else if (cnt > k) removeAt(ref t.lst, k); else { if (cnt == 0) { t = t.rst; return; } if (t.rst.Count == 0) { t = t.lst; return; } t.Key = find(t.lst, k - 1); removeAt(ref t.lst, k - 1); } balance(ref t); } private void balance(ref Node t) { long balance = t.lst.Height - t.rst.Height; if (balance == -2) { if (t.rst.lst.Height - t.rst.rst.Height > 0) { rotR(ref t.rst); } rotL(ref t); } else if (balance == 2) { if (t.lst.lst.Height - t.lst.rst.Height < 0) rotL(ref t.lst); rotR(ref t); } else t.Update(); } private T find(Node t, long k) { if (k < 0 || k > root.Count) throw new ArgumentOutOfRangeException(); while (true) { if (k == t.lst.Count) return t.Key; else if (k < t.lst.Count) t = t.lst; else { k -= t.lst.Count + 1; t = t.rst; } } } /// /// コレクションに含まれる要素であって、 v 以上の最小の要素の番号を返します。 /// /// この操作は計算量 O(log N) で実行されます. internal long LowerBound(T v) { // 追加機能 件数が0なら-1を返す if (this.Count == 0) { return -1; } // 追加機能 v 以上な要素が無い場合は-1を返す T MaxVal = this[this.Count - 1]; int cmp = comparer.Compare(MaxVal, v); if (cmp == -1) return -1; long k = 0; Node t = root; while (true) { if (t.Count == 0) return k; if (comparer.Compare(v, t.Key) <= 0) t = t.lst; else { k += t.lst.Count + 1; t = t.rst; } } } /// /// コレクションに含まれる要素であって、 v より真に大きい、最小の要素の番号を返します。 /// /// この操作は計算量 O(log N) で実行されます. internal long UpperBound(T v) { // 追加機能 件数が0なら-1を返す if (this.Count == 0) { return -1; } // 追加機能 v 超えな要素が無い場合は-1を返す T MaxVal = this[this.Count - 1]; int cmp = comparer.Compare(MaxVal, v); if (cmp <= 0) return -1; long k = 0; Node t = root; while (true) { if (t.Count == 0) return k; if (comparer.Compare(t.Key, v) <= 0) { k += t.lst.Count + 1; t = t.rst; } else t = t.lst; } } // 追加機能01 V未満で最大の要素の番号を返す internal long Lower_Max(T v) { // 件数が0なら-1を返す if (this.Count == 0) { return -1; } // v 未満な要素が無い場合は-1を返す T MinVal = this[0]; int cmp = comparer.Compare(MinVal, v); if (cmp >= 0) return -1; // v 以上の件数を調べる long More_Or_Equal_cnt = this.Count; long UB = this.Count - 1; long LowerB = LowerBound(v); if (IsValidInd(LowerB)) { More_Or_Equal_cnt -= (UB - LowerB + 1); } return More_Or_Equal_cnt - 1; } // 追加機能02 V以下で最大の要素の番号を返す internal long LowerOrEqual_Max(T v) { // 件数が0なら-1を返す if (this.Count == 0) { return -1; } // v 以下な要素が無い場合は-1を返す T MinVal = this[0]; int cmp = comparer.Compare(MinVal, v); if (cmp > 0) return -1; // v 超えの件数を調べる long More_cnt = this.Count; long UB = this.Count - 1; long UpperB = UpperBound(v); if (IsValidInd(UpperB)) { More_cnt -= (UB - UpperB + 1); } return More_cnt - 1; } // 追加機能03 LowerBoundなどで返したIndが、有効範囲かを判定 internal bool IsValidInd(long pInd) { if (pInd < 0) return false; if (this.Count <= pInd) return false; return true; } // 追加機能04 Vを含むかを返す internal bool Contains(T v) { long LowerB = LowerBound(v); if (IsValidInd(LowerB) == false) { return false; } int cmp = comparer.Compare(this[LowerB], v); return cmp == 0; } // 追加機能05 Min以上な値の個数を返す internal long GetMoreOrEqualCnt(T pMinVal) { long ResultInd = LowerBound(pMinVal); if (IsValidInd(ResultInd) == false) return 0; return Count - 1 - ResultInd + 1; } // 追加機能06 Min超えな値の個数を返す internal long GetMoreStrictCnt(T pMinVal) { long ResultInd = UpperBound(pMinVal); if (IsValidInd(ResultInd) == false) return 0; return Count - 1 - ResultInd + 1; } // 追加機能07 Max以下な値の個数を返す internal long GetLessOrEqualCnt(T pMaxVal) { long ResultInd = LowerOrEqual_Max(pMaxVal); if (IsValidInd(ResultInd) == false) return 0; return ResultInd + 1; } // 追加機能08 Max未満な値の個数を返す internal long GetLessStrictCnt(T pMaxVal) { long ResultInd = Lower_Max(pMaxVal); if (ResultInd == -1) return 0; return ResultInd + 1; } // 追加機能09 Min以上Max以下な値の個数を返す internal long GetRangeCnt(T pMinVal, T pMaxVal) { long ResultInd1 = LowerBound(pMinVal); if (IsValidInd(ResultInd1) == false) return 0; long ResultInd2 = LowerOrEqual_Max(pMaxVal); if (IsValidInd(ResultInd2) == false) return 0; if (ResultInd1 > ResultInd2) return 0; return ResultInd2 - ResultInd1 + 1; } private void rotR(ref Node t) { Node l = t.lst; t.lst = l.rst; l.rst = t; t.Update(); l.Update(); t = l; } private void rotL(ref Node t) { Node r = t.rst; t.rst = r.lst; r.lst = t; t.Update(); r.Update(); t = r; } class Node { internal Node(T key) { Key = key; } internal long Count { get; private set; } internal long Height { get; private set; } internal T Key { get; set; } internal Node lst, rst; internal void Update() { Count = 1 + lst.Count + rst.Count; Height = 1 + Math.Max(lst.Height, rst.Height); } public override string ToString() { return string.Format("Count = {0}, Key = {1}", Count, Key); } } } #endregion