結果

問題 No.3265 地元に帰れば天才扱い!
ユーザー Nauclhlt🪷
提出日時 2025-09-06 14:28:21
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 2,363 ms / 2,500 ms
コード長 7,503 bytes
コンパイル時間 2,626 ms
コンパイル使用メモリ 212,176 KB
実行使用メモリ 25,216 KB
最終ジャッジ日時 2025-09-06 14:29:22
合計ジャッジ時間 54,528 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 21
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;

using ll = long long;

// C++に書き換えただけで通る??

template <typename T, typename M, T OP(T, T), T MAPPING(T, M, int), T COMPOSITION(T, T)>
class LazySegmentTree
{
private:
    int _treeSize;
    int _dataSize;
    int _originalDataSize;
    vector<T> _data;
    vector<optional<T>> _lazy;
    T _identity;

public:
    LazySegmentTree(int n, T identity)
    {
        _originalDataSize = n;
        _identity = identity;

        int size = 1;
        while (n > size)
        {
            size <<= 1;
        }

        _dataSize = size;
        _treeSize = 2 * size - 1;

        _data.resize(_treeSize, _identity);
        _lazy.resize(_treeSize, nullopt);
    }

    void Build(vector<T>& array)
    {
        if (_originalDataSize != (int)array.size())
        {
            throw exception();
        }

        for (int i = 0; i < (int)array.size(); i++)
        {
            _data[i + _dataSize - 1] = array[i];
        }

        for (int i = _dataSize - 2; i >= 0; i--)
        {
            _data[i] = OP(_data[(i << 1) + 1], _data[(i << 1) + 2]);
        }
    }

    int TreeSize()
    {
        return _treeSize;
    }

    int OriginalDataSize()
    {
        return _originalDataSize;
    }

    void Apply(int left, int right, M m)
    {
        ApplyRec(left, right, m, 0, 0, _dataSize);
    }

    T Query(int left, int right)
    {
        return QueryRec(left, right, 0, 0, _dataSize);
    }

    T GetByIndex(int index)
    {
        return AccessRec(index, 0, 0, _dataSize);
    }

private:
    void Evaluate(int index, int l, int r)
    {
        if (!_lazy[index].has_value())
        {
            return;
        }

        if (index < _dataSize - 1)
        {
            _lazy[(index << 1) + 1] = GuardComposition(_lazy[(index << 1) + 1], _lazy[index]);
            _lazy[(index << 1) + 2] = GuardComposition(_lazy[(index << 1) + 2], _lazy[index]);
        }

        _data[index] = MAPPING(_data[index], _lazy[index].value(), r - l);
        _lazy[index] = nullopt;
    }

    optional<M> GuardComposition(optional<M> a, optional<M> b)
    {
        if (!a.has_value())
        {
            return b;
        }
        else
        {
            return COMPOSITION(a.value(), b.value());
        }
    }

    void ApplyRec(int left, int right, M m, int index, int l, int r)
    {
        Evaluate(index, l, r);

        if (left <= l && r <= right)
        {
            _lazy[index] = GuardComposition(_lazy[index], m);
            Evaluate(index, l, r);
        }
        else if (left < r && l < right)
        {
            ApplyRec(left, right, m, (index << 1) + 1, l, (l + r) / 2);
            ApplyRec(left, right, m, (index << 1) + 2, (l + r) / 2, r);
            _data[index] = OP(_data[(index << 1) + 1], _data[(index << 1) + 2]);
        }
    }

    T QueryRec(int left, int right, int index, int l, int r)
    {
        Evaluate(index, l, r);

        if (left >= r || right <= l)
        {
            return _identity;
        }

        if (left <= l && r <= right)
        {
            return _data[index];
        }

        return OP(QueryRec(left, right, (index << 1) + 1, l, (l + r) / 2), QueryRec(left, right, (index << 1) + 2, (l + r) / 2, r));
    }

    T AccessRec(int target, int index, int l, int r)
    {
        Evaluate(index, l, r);

        if (index >= _dataSize - 1)
        {
            return _data[index];
        }

        int mid = (l + r) / 2;
        
        if (target < mid)
        {
            return AccessRec(target, (index << 1) + 1, l, mid);
        }
        else
        {
            return AccessRec(target, (index << 1) + 2, mid, r);
        }
    }
};

template<typename T, T OP(T, T), T APPLY(T, T)>
class SegmentTree
{
private:
    int _treeSize;
    int _dataSize;
    int _originalDataSize;
    vector<T> _data;
    T _identity;

public:
    SegmentTree(int n, T identity)
    {
        _originalDataSize = n;
        _identity = identity;

        int size = 1;
        while (n > size)
        {
            size <<= 1;
        }

        _dataSize = size;
        _treeSize = 2 * size - 1;

        _data.resize(_treeSize, _identity);
    }

    int OriginalDataSize()
    {
        return _originalDataSize;
    }

    int TreeSize()
    {
        return _treeSize;
    }

    T Identity()
    {
        return _identity;
    }

    void Build(vector<T>& array)
    {
        if (_originalDataSize != (int)array.size())
        {
            throw exception();
        }

        for (int i = 0; i < (int)array.size(); i++)
        {
            _data[i + _dataSize - 1] = array[i];
        }

        for (int i = _dataSize - 2; i >= 0; i--)
        {
            _data[i] = OP(_data[(i << 1) + 1], _data[(i << 1) + 2]);
        }
    }

    void Apply(int index, T value)
    {
        index += _dataSize - 1;
        _data[index] = APPLY(_data[index], value);

        while (index > 0)
        {
            index = (index - 1) >> 1;
            _data[index] = OP(_data[(index << 1) + 1], _data[(index << 1) + 2]);
        }
    }

    T Query(int left, int right)
    {
        return QueryRec(left, right, 0, 0, _dataSize);
    }

    const T& operator[](size_t index) const
    {
        return _data[_dataSize - 1 + index];
    }

    T& operator[](size_t index)
    {
        return _data[_dataSize - 1 + index];
    }

private:
    T QueryRec(int left, int right, int index, int l, int r)
    {
        if (left >= r || right <= l)
        {
            return _identity;
        }

        if (left <= l && r <= right)
        {
            return _data[index];
        }

        return OP(QueryRec(left, right, (index << 1) + 1, l, (l + r) / 2), QueryRec(left, right, (index << 1) + 2, (l + r) / 2, r));
    }
};

ll update(ll x, ll a)
{
    return a;
}

ll add(ll x, ll y)
{
    return x + y;
}

ll mapping(ll x, ll a, int len)
{
    return x + a * len;
}

int main(int argc, char** argv)
{
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int N, M;
    cin >> N >> M;
    vector<ll> A(N);
    vector<int> L(N);
    vector<int> R(N);
    for (int i = 0; i < N; i++)
    {
        cin >> A[i] >> L[i] >> R[i];
        L[i]--;
        R[i]--;
    }
    vector<int> home(N);
    for (int i = 0; i < N; i++) home[i] = i;
    vector<ll> B(M);
    for (int i = 0; i < N; i++) B[i] = A[i];
    SegmentTree<ll, add, update> seg(M, 0LL);
    LazySegmentTree<ll, ll, add, mapping, add> nseg(M, 0LL);
    seg.Build(B);
    for (int i = 0; i < N; i++)
    {
        nseg.Apply(L[i], R[i] + 1, 1);
    }
    long sum = 0;
    for (int i = 0; i < N; i++)
    {
        sum += A[i] * (R[i] - L[i] + 1) - seg.Query(L[i], R[i] + 1);
    }

    int Q;
    cin >> Q;
    for (int i = 0; i < Q; i++)
    {
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        x--; y--; u--; v--;
        // 差分更新を、がんばる

        int from = home[x];

        sum -= A[x] * (R[x] - L[x] + 1);
        sum += seg.Query(L[x], R[x] + 1);

        sum += A[x] * nseg.GetByIndex(from);
        if (L[x] <= from && from <= R[x]) sum -= A[x];

        seg.Apply(y, A[x]);
        seg.Apply(from, 0);
        nseg.Apply(L[x], R[x] + 1, -1);
        home[x] = y;
        L[x] = u;
        R[x] = v;
        nseg.Apply(u, v + 1, 1);

        sum += A[x] * (v - u + 1);
        sum -= seg.Query(u, v + 1);

        sum -= A[x] * nseg.GetByIndex(y);
        if (u <= y && y <= v) sum += A[x];

        cout << sum << endl;
    }
}
0