AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC366-E Manhattan Multifocal Ellipse
C#のソース
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("2 3");
WillReturn.Add("0 0");
WillReturn.Add("1 0");
//8
}
else if (InputPattern == "Input2") {
WillReturn.Add("2 0");
WillReturn.Add("0 0");
WillReturn.Add("2 0");
//0
}
else if (InputPattern == "Input3") {
WillReturn.Add("6 100");
WillReturn.Add("9 -6");
WillReturn.Add("10 -1");
WillReturn.Add("2 10");
WillReturn.Add("-1 7");
WillReturn.Add("-7 5");
WillReturn.Add("-1 -4");
//419
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long mD;
struct PointDef
{
internal long X;
internal long Y;
}
static List<PointDef> mPointList = new List<PointDef>();
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]);
mD = wkArr[1];
foreach (string EachStr in InputList.Skip(1)) {
SplitAct(EachStr);
PointDef WillAdd;
WillAdd.X = wkArr[0];
WillAdd.Y = wkArr[1];
mPointList.Add(WillAdd);
}
List<long> DistanceListX = DeriveDistanceList(mPointList.Select(pX => pX.X).ToArray());
List<long> DistanceListY = DeriveDistanceList(mPointList.Select(pX => pX.Y).ToArray());
DistanceListX.Sort();
DistanceListY.Sort();
long Answer = 0;
foreach (long EachVal in DistanceListX) {
long RestVal = mD - EachVal;
int ResultInd = ExecNibunhou_LowerOrEqual_Max(RestVal, DistanceListY);
if (ResultInd == -1) continue;
Answer += ResultInd + 1;
}
Console.WriteLine(Answer);
}
// 成分の配列を引数とし、距離のListを返す
static List<long> DeriveDistanceList(long[] pPosArr)
{
var WillReturn = new List<long>();
Array.Sort(pPosArr);
var InsLinkedList = new LinkedList<long>(pPosArr);
long LeftCnt = 0;
long RightCnt = InsLinkedList.Count;
long StaPos = pPosArr.Min() - mD;
long EndPos = pPosArr.Max() + mD;
long DictanceSum = pPosArr.Sum(pX => pX - StaPos);
for (long I = StaPos; I <= EndPos; I++) {
WillReturn.Add(DictanceSum);
while (true) {
if (InsLinkedList.Count > 0 && InsLinkedList.First.Value == I) {
LeftCnt++;
RightCnt--;
InsLinkedList.RemoveFirst();
}
else break;
}
DictanceSum -= RightCnt;
DictanceSum += LeftCnt;
}
WillReturn.RemoveAll(pX => pX > mD);
return WillReturn;
}
// 二分法で、Val以下で最大の値を持つ、添字を返す
static int ExecNibunhou_LowerOrEqual_Max(long pVal, List<long> pList)
{
if (pList.Count == 0) return -1;
// 最後の要素がVal以下の特殊ケース
if (pVal >= pList.Last()) {
return pList.Count - 1;
}
// 最初の要素がVal超えの特殊ケース
if (pVal < pList[0]) {
return -1;
}
int L = 0;
int R = pList.Count - 1;
while (L + 1 < R) {
int Mid = (L + R) / 2;
if (pList[Mid] <= pVal) {
L = Mid;
}
else {
R = Mid;
}
}
return L;
}
}
解説
X座標とY座標で独立で考え、
候補となる座標ごとの距離のListを作ってから、
二分探索で組み合わせ数を列挙してます。