using System; using System.Collections.Generic; using System.Linq; // https://yukicoder.me/problems/no/3327 class Program { static string InputPattern = "InputX"; static List GetInputList() { var WillReturn = new List(); if (InputPattern == "Input1") { WillReturn.Add("5 4"); WillReturn.Add("3 5 8 1 4"); WillReturn.Add("1 4"); WillReturn.Add("2 7"); WillReturn.Add("2 4"); WillReturn.Add("1 3"); //2 //3 //-1 //5 } 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[] AArr = GetSplitArr(InputList[1]); long UB = AArr.GetUpperBound(0); var InsSegmentTree = new SegmentTree(UB, long.MinValue); for (long I = 0; I <= UB; I++) { InsSegmentTree[I] = AArr[I]; } long[] wkArr = { }; Action SplitAct = (pStr) => wkArr = GetSplitArr(pStr); foreach (string EachStr in InputList.Skip(2)) { SplitAct(EachStr); long C = wkArr[0]; long Shikii = wkArr[1]; long MaxVal = InsSegmentTree.Internal_Query(0, UB); if (MaxVal <= Shikii) { Console.WriteLine(-1); continue; } if (C == 1) { // 二分探索を行う long L = 0, R = UB; while (L + 1 < R) { long Mid = (L + R) / 2; long LeftMax = InsSegmentTree.Internal_Query(0, Mid); if (LeftMax > Shikii) R = Mid; else L = Mid; } long TargetInd = ((InsSegmentTree.Internal_Query(L, L) > Shikii) ? L : R); Console.WriteLine(TargetInd + 1); InsSegmentTree[TargetInd] = long.MinValue; } if (C == 2) { // 二分探索を行う long L = 0, R = UB; while (L + 1 < R) { long Mid = (L + R) / 2; long RightMax = InsSegmentTree.Internal_Query(Mid, R); if (RightMax > Shikii) L = Mid; else R = Mid; } long TargetInd = ((InsSegmentTree.Internal_Query(R, R) > Shikii) ? R : L); Console.WriteLine(TargetInd + 1); InsSegmentTree[TargetInd] = long.MinValue; } } } } #region SegmentTree // SegmentTreeクラス (RMaxQ and 1点更新) internal class SegmentTree { private long[] mTreeNodeArr; private long UB; // 木のノードの配列のUB private long mLeafCnt; // 葉ノードの数 private long mExternalArrUB; /* // 拡張機能 (最大値と、最大値を持つIndを返す) // 最大値が複数あったら、左側のIndを優先 internal void GetMaxInfo_Left(long pShikii, long pSearchStaInd, long pSearchEndInd, out long pMaxVal, out long pMaxValInd) { // 区間の最大値を求める pMaxVal = Internal_Query(pSearchStaInd, pSearchEndInd); if (pMaxVal > pShikii + 1) { pMaxVal = pShikii + 1; } // 二分探索を行う long L = pSearchStaInd, R = pSearchEndInd; while (L + 1 < R) { long Mid = (L + R) / 2; long LeftMax = Internal_Query(L, Mid); LeftMax = Math.Min(pShikii + 1, LeftMax); if (LeftMax == pMaxVal) R = Mid; else L = Mid; } pMaxValInd = ((Internal_Query(L, L) == pMaxVal) ? L : R); } // 拡張機能 (最大値と、最大値を持つIndを返す) // 最大値が複数あったら、右側のIndを優先 internal void GetMaxInfo_Right(long pShikii, long pSearchStaInd, long pSearchEndInd, out long pMaxVal, out long pMaxValInd) { // 区間の最大値を求める pMaxVal = Internal_Query(pSearchStaInd, pSearchEndInd); if (pMaxVal > pShikii + 1) { pMaxVal = pShikii + 1; } // 二分探索を行う long L = pSearchStaInd, R = pSearchEndInd; while (L + 1 < R) { long Mid = (L + R) / 2; long RightMax = Internal_Query(Mid, R); RightMax = Math.Min(pShikii + 1, RightMax); if (RightMax == pMaxVal) L = Mid; else R = Mid; } pMaxValInd = ((Internal_Query(R, R) == pMaxVal) ? R : L); } * */ // ノードの添字を引数とし、範囲の開始添字と終了添字を持つ配列 private struct RangeInfoDef { internal long StaInd; internal long EndInd; } private RangeInfoDef[] mRangeInfo; // ノードのIndexの列挙を返す internal IEnumerable GetNodeIndEnum() { for (long I = 0; I <= mExternalArrUB; I++) { yield return I; } } // 木のノードのUBを返す internal long GetUB() { return mExternalArrUB; } // コンストラクタ internal SegmentTree(long pExternalArrUB, long pInitVal) { mExternalArrUB = pExternalArrUB; // 簡単のため、葉ノード数を2のべき乗に long ArrLength = 0; for (long I = 1; I < long.MaxValue; I *= 2) { ArrLength += I; mLeafCnt = I; if (pExternalArrUB + 1 < mLeafCnt) break; } // すべての値をpInitValに UB = ArrLength - 1; mTreeNodeArr = new long[UB + 1]; for (long I = 0; I <= UB; I++) { mTreeNodeArr[I] = pInitVal; } // ノードの添字を引数とし、範囲の開始添字と終了添字を持つ配列の作成 mRangeInfo = new RangeInfoDef[UB + 1]; for (long I = 0; I <= UB; I++) { if (I == 0) { RangeInfoDef WillSet1; WillSet1.StaInd = 0; WillSet1.EndInd = mLeafCnt - 1; mRangeInfo[I] = WillSet1; continue; } long ParentNode = DeriveParentNode(I); RangeInfoDef ParentRangeInfo = mRangeInfo[ParentNode]; RangeInfoDef WillSet2; long Mid = (ParentRangeInfo.StaInd + ParentRangeInfo.EndInd) / 2; if (I % 2 == 1) { // 奇数ノードの場合 WillSet2.StaInd = ParentRangeInfo.StaInd; WillSet2.EndInd = Mid; } else { // 偶数ノードの場合 WillSet2.StaInd = Mid + 1; WillSet2.EndInd = ParentRangeInfo.EndInd; } mRangeInfo[I] = WillSet2; } } // インデクサ internal long this[long pInd] { get { return Internal_Query(pInd, pInd); } set { Update(pInd, value); } } // 親ノードの添字を取得 private long DeriveParentNode(long pTarget) { return (pTarget - 1) / 2; } // 子ノードの添字(小さいほう)を取得 private long DeriveChildNode(long pTarget) { return pTarget * 2 + 1; } // 葉ノードの配列の添字を木の添字に変換して返す private long DeriveTreeNode(long pLeafArrInd) { long BaseInd = UB - mLeafCnt + 1; return BaseInd + pLeafArrInd; } // 葉ノードの配列のK番目の値をNewValに変更 internal void Update(long pK, long pNewVal) { long CurrNode = DeriveTreeNode(pK); mTreeNodeArr[CurrNode] = pNewVal; // 登りながら更新 while (CurrNode > 0) { CurrNode = DeriveParentNode(CurrNode); long ChildNode1 = DeriveChildNode(CurrNode); long ChildNode2 = ChildNode1 + 1; mTreeNodeArr[CurrNode] = Math.Max(mTreeNodeArr[ChildNode1], mTreeNodeArr[ChildNode2]); } } // 開始添字と終了添字とカレントノードを引数として、最大値を返す internal long Internal_Query(long pSearchStaInd, long pSearchEndInd) { return Private_Query(pSearchStaInd, pSearchEndInd, 0); } private long Private_Query(long pSearchStaInd, long pSearchEndInd, long pCurrNode) { long CurrNodeStaInd = mRangeInfo[pCurrNode].StaInd; long CurrNodeEndInd = mRangeInfo[pCurrNode].EndInd; // OverLapしてなければ、long.MinValue if (CurrNodeEndInd < pSearchStaInd || pSearchEndInd < CurrNodeStaInd) return long.MinValue; // 完全に含んでいれば、このノードの値 if (pSearchStaInd <= CurrNodeStaInd && CurrNodeEndInd <= pSearchEndInd) return mTreeNodeArr[pCurrNode]; // そうでなければ、2つの子の最大値 long ChildNode1 = DeriveChildNode(pCurrNode); long ChildNode2 = ChildNode1 + 1; long ChildVal1 = Private_Query(pSearchStaInd, pSearchEndInd, ChildNode1); long ChildVal2 = Private_Query(pSearchStaInd, pSearchEndInd, ChildNode2); return Math.Max(ChildVal1, ChildVal2); } } #endregion