AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC128-E Roadwork
C++のソース
#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>
std::vector<std::string> GetInputValues();
std::string InputPattern = "InputX";
std::vector<std::string> GetInputValues()
{
std::vector<std::string> InputValuesVect;
if (InputPattern == "Input1") {
InputValuesVect.push_back("4 6");
InputValuesVect.push_back("1 3 2");
InputValuesVect.push_back("7 13 10");
InputValuesVect.push_back("18 20 13");
InputValuesVect.push_back("3 4 2");
InputValuesVect.push_back("0");
InputValuesVect.push_back("1");
InputValuesVect.push_back("2");
InputValuesVect.push_back("3");
InputValuesVect.push_back("5");
InputValuesVect.push_back("8");
}
else { //実際の入力
while (true) {
std::string wkStr;
std::getline(std::cin, wkStr);
if (std::cin.eof()) break;
InputValuesVect.push_back(wkStr.c_str());
}
}
return InputValuesVect;
}
struct STXInfoDef
{
int S;
int T;
int X;
bool operator<(const STXInfoDef& right) const {
return X < right.X;
}
};
int main()
{
std::vector<std::string> InputVect = GetInputValues();
int N;
int SpaceInd = InputVect.at(0).find_first_of(" ");
std::istringstream iss1(InputVect.at(0).substr(0, SpaceInd));
iss1 >> N;
std::vector<STXInfoDef> STXInfoVect;
for (int I = 1; I <= N; I++) {
std::vector<int> NumVect;
std::istringstream iss3(InputVect.at(I));
while (iss3.eof() == false) {
int wkInt;
iss3 >> wkInt;
NumVect.push_back(wkInt);
}
STXInfoDef WillAdd;
WillAdd.S = NumVect.at(0);
WillAdd.T = NumVect.at(1) - 1; // 開区間を閉区間に変更するのでマイナス1
WillAdd.X = NumVect.at(2);
WillAdd.S -= WillAdd.X;
WillAdd.T -= WillAdd.X;
if (WillAdd.S < 0) {
WillAdd.S = 0;
}
STXInfoVect.push_back(WillAdd);
}
std::vector<int> DVect;
std::set<int> DSet;
for (int I = N + 1; I <= (int)InputVect.size() - 1; I++) {
int D = atoi(InputVect.at(I).c_str());
DVect.push_back(D);
DSet.insert(D);
}
sort(STXInfoVect.begin(), STXInfoVect.end());
std::map<int, int> AnswerMap;
for (int I = 0; I <= (int)STXInfoVect.size() - 1; I++) {
int S = STXInfoVect[I].S;
int T = STXInfoVect[I].T;
int X = STXInfoVect[I].X;
std::set<int>::iterator it = DSet.lower_bound(S);
std::vector<int> RemoveVect;
while (it != DSet.end()) {
int D = (*it);
if (T < D) break;
//printf("%dは工事場所%dでストップ\n", D, X);
AnswerMap[D] = X;
RemoveVect.push_back(D);
it++;
}
for (int I = 0; I <= (int)RemoveVect.size() - 1; I++) {
DSet.erase(RemoveVect[I]);
}
}
for (int I = 0; I <= (int)DVect.size() - 1; I++) {
int CurrD = DVect.at(I);
if (AnswerMap.find(CurrD) != AnswerMap.end()) {
printf("%d\n", AnswerMap[CurrD]);
}
else {
puts("-1");
}
}
}
C#のソース(RBSTでC++のsetを模倣する方法)
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("4 6");
WillReturn.Add("1 3 2");
WillReturn.Add("7 13 10");
WillReturn.Add("18 20 13");
WillReturn.Add("3 4 2");
WillReturn.Add("0");
WillReturn.Add("1");
WillReturn.Add("2");
WillReturn.Add("3");
WillReturn.Add("5");
WillReturn.Add("8");
//2
//2
//10
//-1
//13
//-1
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
class BlockInfoDef
{
internal int RangeSta;
internal int RangeEnd;
internal int BlockPos;
}
static void Main()
{
List<string> InputList = GetInputList();
int[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => int.Parse(pX)).ToArray();
SplitAct(InputList[0]);
int N = wkArr[0];
var BlockInfoList = new List<BlockInfoDef>();
foreach (string EachStr in InputList.Skip(1).Take(N)) {
SplitAct(EachStr);
BlockInfoDef WillAdd = new BlockInfoDef();
WillAdd.RangeSta = wkArr[0];
WillAdd.RangeEnd = wkArr[1] - 1; // 開区間を閉区間に変更するのでマイナス1
WillAdd.BlockPos = wkArr[2];
WillAdd.RangeSta -= WillAdd.BlockPos;
WillAdd.RangeEnd -= WillAdd.BlockPos;
if (WillAdd.RangeSta < 0) {
WillAdd.RangeSta = 0;
}
BlockInfoList.Add(WillAdd);
}
int[] DArr = InputList.Skip(1 + N).Select(pX => int.Parse(pX)).ToArray();
var Ins_CPP_Set = new CPP_Set<int>();
Array.ForEach(DArr, pX => Ins_CPP_Set.Insert(pX));
var Query = BlockInfoList.OrderBy(pX => pX.BlockPos).ThenBy(pX => pX.RangeSta).ToList();
var AnswerDict = new Dictionary<int, int>();
foreach (BlockInfoDef EachBlockInfo in Query) {
int LB = Ins_CPP_Set.LowerBound(EachBlockInfo.RangeSta);
if (Ins_CPP_Set.IsValidInd(LB) == false) continue;
var RemoveList = new List<int>();
for (int I = Ins_CPP_Set.LowerBound(EachBlockInfo.RangeSta); I <= Ins_CPP_Set.Count() - 1; I++) {
int EachKey = Ins_CPP_Set[I];
if (EachBlockInfo.RangeEnd < EachKey) break;
if (EachBlockInfo.RangeSta <= EachKey && EachKey <= EachBlockInfo.RangeEnd) {
AnswerDict[EachKey] = EachBlockInfo.BlockPos;
RemoveList.Add(EachKey);
}
}
RemoveList.ForEach(pX => Ins_CPP_Set.Remove(pX));
}
var sb = new System.Text.StringBuilder();
foreach (int EachD in DArr) {
if (AnswerDict.ContainsKey(EachD)) {
sb.AppendLine(AnswerDict[EachD].ToString());
}
else {
sb.AppendLine("-1");
}
}
Console.Write(sb.ToString());
}
}
#region CPP_Set_MultiSet
// Self-Balancing Binary Search Tree
// (using Randamized BST)
internal class SB_BinarySearchTree<T> where T : IComparable
{
internal class Node
{
internal T Value;
internal Node LChild;
internal Node RChild;
internal int Count; // 部分木のサイズ
internal Node(T v)
{
Value = v;
Count = 1;
}
}
static Random _rnd = new Random();
internal static int Count(Node t)
{
return t == null ? 0 : t.Count;
}
static Node Update(Node t)
{
t.Count = Count(t.LChild) + Count(t.RChild) + 1;
return t;
}
internal static Node Merge(Node l, Node r)
{
if (l == null || r == null) return l == null ? r : l;
if ((double)Count(l) / (double)(Count(l) + Count(r)) > _rnd.NextDouble()) {
l.RChild = Merge(l.RChild, r);
return Update(l);
}
r.LChild = Merge(l, r.LChild);
return Update(r);
}
// C#4.0のTuppleクラスもどき
internal struct CS4_Tupple_Node
{
internal Node mItem1;
internal Node mItem2;
internal CS4_Tupple_Node(Node pItem1, Node pItem2)
{
mItem1 = pItem1;
mItem2 = pItem2;
}
}
// split as [0, k), [k, n)
internal static CS4_Tupple_Node Split(Node t, int k)
{
if (t == null) return new CS4_Tupple_Node(null, null);
if (k <= Count(t.LChild)) {
CS4_Tupple_Node s = Split(t.LChild, k);
t.LChild = s.mItem2;
return new CS4_Tupple_Node(s.mItem1, Update(t));
}
else {
CS4_Tupple_Node s = Split(t.RChild, k - Count(t.LChild) - 1);
t.RChild = s.mItem1;
return new CS4_Tupple_Node(Update(t), s.mItem2);
}
}
internal static Node Remove(Node t, T v)
{
if (Find(t, v) == null) return t;
return RemoveAt(t, LowerBound(t, v));
}
internal static Node RemoveAt(Node t, int k)
{
CS4_Tupple_Node s = Split(t, k);
CS4_Tupple_Node s2 = Split(s.mItem2, 1);
return Merge(s.mItem1, s2.mItem2);
}
internal static bool Contains(Node t, T v)
{
return Find(t, v) != null;
}
internal static Node Find(Node t, T v)
{
while (t != null) {
int cmp = t.Value.CompareTo(v);
if (cmp > 0) t = t.LChild;
else if (cmp < 0) t = t.RChild;
else break;
}
return t;
}
internal static Node FindByIndex(Node t, int idx)
{
if (t == null) return null;
int currentIdx = Count(t) - Count(t.RChild) - 1;
while (t != null) {
if (currentIdx == idx) return t;
if (currentIdx > idx) {
t = t.LChild;
currentIdx -= (Count(t == null ? null : t.RChild) + 1);
}
else {
t = t.RChild;
currentIdx += (Count(t == null ? null : t.LChild) + 1);
}
}
return null;
}
internal static int UpperBound(Node t, T v)
{
Node torg = t;
if (t == null) return -1;
int ret = int.MaxValue;
int idx = Count(t) - Count(t.RChild) - 1;
while (t != null) {
int cmp = t.Value.CompareTo(v);
if (cmp > 0) {
ret = Math.Min(ret, idx);
t = t.LChild;
idx -= (Count(t == null ? null : t.RChild) + 1);
}
else if (cmp <= 0) {
t = t.RChild;
idx += (Count(t == null ? null : t.LChild) + 1);
}
}
return ret == int.MaxValue ? Count(torg) : ret;
}
internal static int LowerBound(Node t, T v)
{
Node torg = t;
if (t == null) return -1;
int idx = Count(t) - Count(t.RChild) - 1;
int ret = int.MaxValue;
while (t != null) {
int cmp = t.Value.CompareTo(v);
if (cmp >= 0) {
if (cmp == 0) ret = Math.Min(ret, idx);
t = t.LChild;
if (t == null) ret = Math.Min(ret, idx);
idx -= t == null ? 0 : (Count(t.RChild) + 1);
}
else if (cmp < 0) {
t = t.RChild;
idx += (Count(t == null ? null : t.LChild) + 1);
if (t == null) return idx;
}
}
return ret == int.MaxValue ? Count(torg) : ret;
}
internal static Node Insert(Node t, T v)
{
int ub = LowerBound(t, v);
return InsertByIdx(t, ub, v);
}
static Node InsertByIdx(Node t, int k, T v)
{
CS4_Tupple_Node s = Split(t, k);
return Merge(Merge(s.mItem1, new Node(v)), s.mItem2);
}
internal static IEnumerable<T> EnumerateList(Node t)
{
var ret = new List<T>();
EnumerateList(t, ret);
return ret;
}
static void EnumerateList(Node t, List<T> ret)
{
if (t == null) return;
EnumerateList(t.LChild, ret);
ret.Add(t.Value);
EnumerateList(t.RChild, ret);
}
internal static IEnumerable<T> EnumerateYield(Node t)
{
if (t != null) {
foreach (var Each in EnumerateYield(t.LChild)) {
yield return Each;
}
yield return t.Value;
foreach (var Each in EnumerateYield(t.RChild)) {
yield return Each;
}
}
}
}
// CPP-Like Set
internal class CPP_Set<T> where T : IComparable
{
protected SB_BinarySearchTree<T>.Node _root;
// 機能01 インデクサ(0オリジン)
internal T this[int idx] { get { return ElementAt(idx); } }
// 機能02 件数を返す
internal int Count()
{
return SB_BinarySearchTree<T>.Count(_root);
}
// 機能03 要素を追加
internal virtual void Insert(T v)
{
if (_root == null) _root = new SB_BinarySearchTree<T>.Node(v);
else {
if (SB_BinarySearchTree<T>.Find(_root, v) != null) return;
_root = SB_BinarySearchTree<T>.Insert(_root, v);
}
}
// 機能04 全ての要素を削除
internal void Clear()
{
_root = null;
}
// 機能05 指定した要素があれば削除
internal void Remove(T v)
{
_root = SB_BinarySearchTree<T>.Remove(_root, v);
}
// 機能06 指定した要素の有無を返す
internal bool Contains(T v)
{
return SB_BinarySearchTree<T>.Contains(_root, v);
}
// 機能07 インデクサの糖衣構文
internal T ElementAt(int k)
{
var node = SB_BinarySearchTree<T>.FindByIndex(_root, k);
if (node == null) throw new IndexOutOfRangeException();
return node.Value;
}
// 機能08 指定した値の件数を返す
internal int Count(T v)
{
return SB_BinarySearchTree<T>.UpperBound(_root, v) -
SB_BinarySearchTree<T>.LowerBound(_root, v);
}
// 機能09 引数以上の最小添字を返す
internal int LowerBound(T v)
{
return SB_BinarySearchTree<T>.LowerBound(_root, v);
}
// 機能10 引数超えの最小添字を返す
internal int UpperBound(T v)
{
return SB_BinarySearchTree<T>.UpperBound(_root, v);
}
// C#4.0のTuppleクラスもどき
internal struct CS4_Tupple_Int
{
internal int mItem1;
internal int mItem2;
internal CS4_Tupple_Int(int pItem1, int pItem2)
{
mItem1 = pItem1;
mItem2 = pItem2;
}
}
// 機能11 引数に等しい範囲の下限と上限を返す
internal CS4_Tupple_Int EqualRange(T v)
{
if (!Contains(v)) return new CS4_Tupple_Int(-1, -1);
return new CS4_Tupple_Int(SB_BinarySearchTree<T>.LowerBound(_root, v),
SB_BinarySearchTree<T>.UpperBound(_root, v) - 1);
}
// 機能12 Listを作って返す
internal List<T> ToList()
{
return new List<T>(SB_BinarySearchTree<T>.EnumerateList(_root));
}
// 機能13 Listでなく列挙を返す
internal IEnumerable<T> EnumerateYield()
{
return SB_BinarySearchTree<T>.EnumerateYield(_root);
}
// 機能14 LowerBoundで返したIndが、有効範囲かを判定
internal bool IsValidInd(int pInd)
{
if (pInd < 0) return false;
if (this.Count() <= pInd) return false;
return true;
}
}
// CPP-Like multiset
internal class CPP_MultiSet<T> : CPP_Set<T> where T : IComparable
{
internal override void Insert(T v)
{
if (_root == null) _root = new SB_BinarySearchTree<T>.Node(v);
else _root = SB_BinarySearchTree<T>.Insert(_root, v);
}
}
#endregion
C#のソース(AVL木でC++のsetを模倣する方法)
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("4 6");
WillReturn.Add("1 3 2");
WillReturn.Add("7 13 10");
WillReturn.Add("18 20 13");
WillReturn.Add("3 4 2");
WillReturn.Add("0");
WillReturn.Add("1");
WillReturn.Add("2");
WillReturn.Add("3");
WillReturn.Add("5");
WillReturn.Add("8");
//2
//2
//10
//-1
//13
//-1
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
class BlockInfoDef
{
internal int RangeSta;
internal int RangeEnd;
internal int BlockPos;
}
static void Main()
{
List<string> InputList = GetInputList();
int[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => int.Parse(pX)).ToArray();
SplitAct(InputList[0]);
int N = wkArr[0];
var BlockInfoList = new List<BlockInfoDef>();
foreach (string EachStr in InputList.Skip(1).Take(N)) {
SplitAct(EachStr);
BlockInfoDef WillAdd = new BlockInfoDef();
WillAdd.RangeSta = wkArr[0];
WillAdd.RangeEnd = wkArr[1] - 1; // 開区間を閉区間に変更するのでマイナス1
WillAdd.BlockPos = wkArr[2];
WillAdd.RangeSta -= WillAdd.BlockPos;
WillAdd.RangeEnd -= WillAdd.BlockPos;
if (WillAdd.RangeSta < 0) {
WillAdd.RangeSta = 0;
}
BlockInfoList.Add(WillAdd);
}
int[] DArr = InputList.Skip(1 + N).Select(pX => int.Parse(pX)).ToArray();
var Ins_AVL_Set = new AVL_Set_MultiSet<int>();
Array.ForEach(DArr, pX => Ins_AVL_Set.Add(pX));
var Query = BlockInfoList.OrderBy(pX => pX.BlockPos).ThenBy(pX => pX.RangeSta).ToList();
var AnswerDict = new Dictionary<int, int>();
foreach (BlockInfoDef EachBlockInfo in Query) {
var RemoveList = new List<int>();
int LB = Ins_AVL_Set.LowerBound(EachBlockInfo.RangeSta);
if (Ins_AVL_Set.IsValidInd(LB) == false) continue;
for (int I = Ins_AVL_Set.LowerBound(EachBlockInfo.RangeSta); I <= Ins_AVL_Set.Count - 1; I++) {
int EachKey = Ins_AVL_Set[I];
if (EachBlockInfo.RangeEnd < EachKey) break;
if (EachBlockInfo.RangeSta <= EachKey && EachKey <= EachBlockInfo.RangeEnd) {
AnswerDict[EachKey] = EachBlockInfo.BlockPos;
RemoveList.Add(EachKey);
}
}
RemoveList.ForEach(pX => Ins_AVL_Set.Remove(pX));
}
var sb = new System.Text.StringBuilder();
foreach (int EachD in DArr) {
if (AnswerDict.ContainsKey(EachD)) {
sb.AppendLine(AnswerDict[EachD].ToString());
}
else {
sb.AppendLine("-1");
}
}
Console.Write(sb.ToString());
}
}
#region AVL_Set_MultiSet
/// <summary>
/// 要素の追加、削除、検索、取得が可能な集合を表します.
/// </summary>
/// <typeparam name="T">優先度付きキュー内の要素の型を指定します.</typeparam>
/// <remarks>内部的にはAVL木によって実装されています.</remarks>
internal class AVL_Set_MultiSet<T>
{
Node root;
readonly IComparer<T> comparer;
readonly Node nil;
/// <summary>
/// 多重集合かどうかを表します.
/// </summary>
internal bool IsMultiSet { get; set; }
internal AVL_Set_MultiSet(IComparer<T> comparer)
{
nil = new Node(default(T));
root = nil;
this.comparer = comparer;
}
internal AVL_Set_MultiSet() : this(Comparer<T>.Default) { }
/// <summary>
/// 要素をコレクションに追加します.
/// </summary>
/// <remarks>この操作は計算量 O(log N) で実行されます.</remarks>
internal bool Add(T v)
{
return insert(ref root, v);
}
/// <summary>
/// v が存在するならコレクションから削除します.
/// </summary>
/// <remarks>この操作は計算量 O(log N) で実行されます.</remarks>
internal bool Remove(T v)
{
return remove(ref root, v);
}
/// <summary>
/// 0-indexed で index 番目の要素をコレクションから取得します.
/// </summary>
/// <remarks>この操作は計算量 O(log N) で実行されます.</remarks>
internal T this[int index] { get { return find(root, index); } }
internal int Count { get { return root.Count; } }
internal void RemoveAt(int k)
{
if (k < 0 || k >= root.Count) throw new ArgumentOutOfRangeException();
removeAt(ref root, k);
}
/// <summary>
/// このコレクションに含まれる要素を昇順に並べて返します.
/// </summary>
/// <remarks>この操作は計算量 O(N) で実行されます.</remarks>
internal T[] Items
{
get
{
T[] ret = new T[root.Count];
int k = 0;
walk(root, ret, ref k);
return ret;
}
}
private void walk(Node t, T[] a, ref int 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, int k)
{
int 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)
{
int 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, int 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; }
}
}
/// <summary>
/// コレクションに含まれる要素であって、 v 以上の最小の要素の番号を返します。
/// </summary>
/// <remarks>この操作は計算量 O(log N) で実行されます.</remarks>
internal int LowerBound(T v)
{
int 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; }
}
}
/// <summary>
/// コレクションに含まれる要素であって、 v より真に大きい、最小の要素の番号を返します。
/// </summary>
/// <remarks>この操作は計算量 O(log N) で実行されます.</remarks>
internal int UpperBound(T v)
{
int 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;
}
}
// 追加機能 V未満で最大の要素の番号を返す
internal int Lower_Max(T v)
{
int UpperB = UpperBound(v);
if (IsValidInd(UpperB - 1)) {
return UpperB - 1;
}
return -1;
}
// 追加機能 V以下で最大の要素の番号を返す
internal int LowerOrEqual_Max(T v)
{
int LowerB = LowerBound(v);
if (IsValidInd(LowerB - 1)) {
return LowerB - 1;
}
return -1;
}
// 追加機能 LowerBoundで返したIndが、有効範囲かを判定
internal bool IsValidInd(int pInd)
{
if (pInd < 0) return false;
if (this.Count <= pInd) return false;
return true;
}
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 int Count { get; private set; }
internal int 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
解説
平衡二分探索木でストップ対象になる人を管理しつつ、
座標の小さい工事場所から
この工事でストップになる人をチェックしてます。