結果

問題 No.3078 Difference Sum Query
ユーザー tobisatis
提出日時 2025-03-28 23:06:03
言語 C#
(.NET 8.0.404)
結果
AC  
実行時間 1,376 ms / 2,000 ms
コード長 6,312 bytes
コンパイル時間 8,444 ms
コンパイル使用メモリ 173,240 KB
実行使用メモリ 196,816 KB
最終ジャッジ日時 2025-03-28 23:06:40
合計ジャッジ時間 33,755 ms
ジャッジサーバーID
(参考情報)
judge5 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2
other AC * 26
権限があれば一括ダウンロードができます
コンパイルメッセージ
  復元対象のプロジェクトを決定しています...
  /home/judge/data/code/main.csproj を復元しました (109 ミリ秒)。
  main -> /home/judge/data/code/bin/Release/net8.0/main.dll
  main -> /home/judge/data/code/bin/Release/net8.0/publish/

ソースコード

diff #

#nullable enable

using System.Numerics;

void Run()
{
    var n = Int();
    var q = Int();
    var az = n.Repeat(() => long.Parse(String()));
    var queries = q.Repeat(() => (Int() - 1, Int() - 1, long.Parse(String())));

    var ss = new long[n + 1];
    for (var i = 0; i < n; i++) ss[i + 1] = ss[i] + az[i];
    var oz = new List<long>(az);
    for (var i = 0; i < q; i++) oz.Add(queries[i].Item3);
    var cas = oz.Compress();
    var spz = new (uint, uint, long)[n];
    var cpz = new (uint, uint, long)[n];
    for (var i = 0; i < n; i++)
    {
        var a = az[i];
        var x = (uint)i;
        var y = (uint)cas[a];
        spz[i] = (x, y, a);
        cpz[i] = (x, y, 1);
    }
    var spm = new PointMap(spz);
    var cpm = new PointMap(cpz);
    var ans = new long[q];
    var uy = (uint)oz.Count;
    for (var i = 0; i < q; i++)
    {
        var (l, r, x) = queries[i];
        var ul = (uint)l;
        var ur = (uint)r + 1;
        var xi = (uint)cas[x];
        var su = spm.Sum((ul, xi), (ur, uy));
        var sv = ss[r + 1] - ss[l] - su;
        var cu = cpm.Sum((ul, xi), (ur, uy));
        var cv = r + 1 - l - cu;
        ans[i] = su - x * cu + x * cv - sv;
    }
    Out(ans);
}

#region
AtCoderIO _io_;
var _backend_ = new StandardIOBackend();
_io_ = new(){ Backend = _backend_ };
Run();
_backend_.Flush();

string String() => _io_.Next();
int Int() => int.Parse(String());
void Out(object? x, string? sep = null) => _io_.Out(x, sep);

class AtCoderIO
{
    public required StandardIOBackend Backend { get; init; }

    Memory<string> _input = Array.Empty<string>();
    int _iter = 0;
    public string Next()
    {
        while (_iter >= _input.Length) (_input, _iter) = (Backend.ReadLine().Split(' '), 0);
        return _input.Span[_iter++];
    }

    public void Out(object? x, string? separator = null)
    {
        if (x == null) return;
        separator ??= Environment.NewLine;
        if (x is System.Collections.IEnumerable a and not string)
        {
            var objects = a.Cast<object>();
            if (separator == Environment.NewLine && !objects.Any()) return;
            x = string.Join(separator, objects);
        }
        Backend.WriteLine(x);
    }
}

class StandardIOBackend
{
    readonly StreamReader _sr = new(Console.OpenStandardInput());
    readonly StreamWriter _sw = new(Console.OpenStandardOutput()) { AutoFlush = false };
    public string ReadLine() => _sr.ReadLine()!;
    public void WriteLine(object? value) => _sw.WriteLine(value);
    public void Flush() => _sw.Flush();
}
#endregion

static class Extensions
{
    public static T[] Repeat<T>(this int time, Func<T> F) => Enumerable.Range(0, time).Select(_ => F()).ToArray();

    public static Dictionary<T, int> Compress<T>(this IEnumerable<T> values) where T : IComparable<T>
    {
        var ordered = values.Distinct().OrderBy(self => self);
        var res = new Dictionary<T, int>();
        var i = 0;
        foreach (var e in ordered) res[e] = i++;
        return res;
    }
}

class WaveletMatrix<T> where T : IAdditionOperators<T, T, T>, ISubtractionOperators<T, T, T>, IAdditiveIdentity<T, T>
{
    const int d = 18;
    uint[,] Rank0 { get; init; }
    T[,] Sum { get; init; }
    int Length => Rank0.GetLength(1) - 1;

    public WaveletMatrix((uint, T)[] array)
    {
        var n = array.Length;
        var ranks = new uint[d, n + 1];
        var sum = new T[d, n + 1];
        var a = array.AsSpan();
        var b = new (uint, T)[n].AsSpan();
        var a0 = new (uint, T)[n].AsSpan();
        var a1 = new (uint, T)[n].AsSpan();
        for (var i = d - 1; i >= 0; i--)
        {
            var (i0, i1) = (0, 0);
            for (var j = 0; j < n; j++)
            {
                ranks[i, j + 1] += ranks[i, j];
                var v = a[j];
                if ((v.Item1 & (1U << i)) > 0)
                {
                    ranks[i, j + 1]++;
                    a1[i1++] = v;
                }
                else a0[i0++] = v;
            }
            for (var j = 0; j < i0; j++) b[j] = a0[j];
            for (var j = 0; j < i1; j++) b[j + i0] = a1[j];
            sum[i, 0] = T.AdditiveIdentity;
            for (var j = 0; j < n; j++) sum[i, j + 1] = sum[i, j] + b[j].Item2;
            var tmp = a; a = b; b = tmp;
        }
        for (var i = 0; i < d; i++) for (var j = 1U; j <= n; j++) ranks[i, j] = j - ranks[i, j];
        (Rank0, Sum) = (ranks, sum);
    }

    public T Frequency(uint l, uint r, uint upper) // [l, r), [0, upper)
    {
        var (n, rank0, sum) = (Length, Rank0, Sum);
        var res = T.AdditiveIdentity;
        for (var i = d - 1; i >= 0; i--)
        {
            if (l >= r) break;
            var (l0, r0) = (rank0[i, l], rank0[i, r]);
            if ((upper & (1U << i)) > 0)
            {
                res += sum[i, r0] - sum[i, l0];
                var zeros = rank0[i, n];
                l += zeros - l0;
                r += zeros - r0;
            }
            else (l, r) = (l0, r0);
        }
        return res;
    }
}

class PointMap
{
    readonly WaveletMatrix<long> matrix;
    readonly uint[] xs;

    public PointMap((uint, uint, long)[] points)
    {
        var sorted = points.OrderBy(e => e.Item1);
        var xs = sorted.Select(e => e.Item1);
        var ys = sorted.Select(e => (e.Item2, e.Item3));
        matrix = new WaveletMatrix<long>(ys.ToArray());
        this.xs = xs.ToArray();
    }

    public long Sum((uint, uint) lowerLeft, (uint, uint) upperRight) // [lx, rx), [ly, ry)
    {
        var (lx, ly) = lowerLeft;
        var (rx, ry) = upperRight;
        if (lx > rx || ly > ry) return 0;
        return Sum(lx, ly, rx - lx, ry - ly);
    }

    public long Sum(uint x, uint y, uint dx, uint dy) // [x, x + dx), [y, y + dy)
    {
        var ux = uint.MaxValue;
        if (x <= ux - dx) ux = x + dx;
        var uy = uint.MaxValue;
        if (y <= uy - dy) uy = y + dy;
        var l = MinIndex(x);
        var r = MinIndex(ux);
        return matrix.Frequency(l, r, uy) - matrix.Frequency(l, r, y);
    }

    uint MinIndex(uint x)
    {
        var xs = this.xs;
        var (l, r) = (-1, xs.Length);
        while (r - l > 1)
        {
            var m = (l + r) >> 1;
            if (xs[m] < x) l = m; else r = m;
        }
        return (uint)r;
    }
}
0