AtCoderのABC    次のABCの問題へ    前のABCの問題へ

ABC432-E Clamp


問題へのリンク


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("3 4");
            WillReturn.Add("4 3 2");
            WillReturn.Add("1 1 7");
            WillReturn.Add("2 3 5");
            WillReturn.Add("1 2 0");
            WillReturn.Add("2 4 2");
            //11
            //12
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("8 10");
            WillReturn.Add("320 578 244 604 145 839 156 857");
            WillReturn.Add("2 400 556");
            WillReturn.Add("1 5 168");
            WillReturn.Add("2 254 62");
            WillReturn.Add("2 145 301");
            WillReturn.Add("1 1 23");
            WillReturn.Add("1 3 0");
            WillReturn.Add("2 413 758");
            WillReturn.Add("2 297 613");
            WillReturn.Add("1 8 451");
            WillReturn.Add("2 598 692");
            //3824
            //2032
            //2073
            //4350
            //3596
            //4884
        }
        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<string> InputList = GetInputList();
        long[] AArr = GetSplitArr(InputList[1]);

        var InsFenwick_Tree_Cnt = new Fenwick_Tree(500000);
        var InsFenwick_Tree_Sum = new Fenwick_Tree(500000);
        long UB = InsFenwick_Tree_Cnt.GetUB();

        foreach (long EachA in AArr) {
            InsFenwick_Tree_Cnt[EachA]++;
            InsFenwick_Tree_Sum[EachA] += EachA;
        }

        long[] wkArr = { };
        Action<string> SplitAct = (pStr) => wkArr = GetSplitArr(pStr);

        foreach (string EachStr in InputList.Skip(2)) {
            SplitAct(EachStr);
            long Type = wkArr[0];
            if (Type == 1) {
                long X = wkArr[1];
                long Y = wkArr[2];

                long BeforeVal = AArr[X - 1];
                InsFenwick_Tree_Cnt[BeforeVal]--;
                InsFenwick_Tree_Sum[BeforeVal] -= BeforeVal;

                long AfterVal = Y;
                InsFenwick_Tree_Cnt[AfterVal]++;
                InsFenwick_Tree_Sum[AfterVal] += AfterVal;
                AArr[X - 1] = AfterVal;
            }
            if (Type == 2) {
                long L = wkArr[1];
                long R = wkArr[2];

                if (L <= R) {
                    long AllSum = InsFenwick_Tree_Sum.GetSum(0, UB);

                    long Minus1 = InsFenwick_Tree_Sum.GetSum(0, L);
                    AllSum -= Minus1;

                    long Minus2 = InsFenwick_Tree_Sum.GetSum(R, UB);
                    AllSum -= Minus2;

                    long Plus1 = L * InsFenwick_Tree_Cnt.GetSum(0, L);
                    AllSum += Plus1;

                    long Plus2 = R * InsFenwick_Tree_Cnt.GetSum(R, UB);
                    AllSum += Plus2;

                    Console.WriteLine(AllSum);
                }
                else {
                    Console.WriteLine(AArr.Length * L);
                }
            }
        }
    }
}

// フェニック木
#region Fenwick_Tree
internal class Fenwick_Tree
{
    private long[] mBitArr;
    private long mExternalArrUB;

    // ノードのIndexの列挙を返す
    internal IEnumerable<long> GetNodeIndEnum()
    {
        for (long I = 0; I <= mExternalArrUB; I++) {
            yield return I;
        }
    }

    // 木のノードのUBを返す
    internal long GetUB()
    {
        return mExternalArrUB;
    }

    // コンストラクタ(外部配列のUBのみ指定)
    internal Fenwick_Tree(long pExternalArrUB)
    {
        mExternalArrUB = pExternalArrUB;

        // フェニック木の外部配列は0オリジンで、
        // フェニック木の内部配列は1オリジンなため、2を足す
        mBitArr = new long[pExternalArrUB + 2];
    }

    // コンストラクタ(初期化用の配列指定)
    internal Fenwick_Tree(long[] pArr)
        : this(pArr.GetUpperBound(0))
    {
        for (long I = 0; I <= pArr.GetUpperBound(0); I++) {
            this.Add(I, pArr[I]);
        }
    }

    // コンストラクタ(初期化用のList指定)
    internal Fenwick_Tree(List<long> pList)
        : this(pList.Count - 1)
    {
        for (int I = 0; I <= pList.Count - 1; I++) {
            this.Add(I, pList[I]);
        }
    }

    // インデクサ
    internal long this[long pInd]
    {
        get { return GetSum(pInd, pInd); }
        set { Add(pInd, value - GetSum(pInd, pInd)); }
    }

    // [pSta,pEnd] のSumを返す
    internal long GetSum(long pSta, long pEnd)
    {
        return GetSum(pEnd) - GetSum(pSta - 1);
    }

    // [0,pEnd] のSumを返す
    internal long GetSum(long pEnd)
    {
        pEnd++; // 1オリジンに変更

        long Sum = 0;
        while (pEnd >= 1) {
            Sum += mBitArr[pEnd];
            pEnd -= pEnd & -pEnd;
        }
        return Sum;
    }

    // [I] に Xを加算
    internal void Add(long pI, long pX)
    {
        pI++; // 1オリジンに変更

        while (pI <= mBitArr.GetUpperBound(0)) {
            mBitArr[pI] += pX;
            pI += pI & -pI;
        }
    }
}
#endregion


解説

値の範囲が狭いので
個数[値]なフェニック木と
合計[値]なフェニック木を用意し、
シュミレーションで解けます。