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を作ってから、
二分探索で組み合わせ数を列挙してます。