結果

問題 No.880 Yet Another Segment Tree Problem
コンテスト
ユーザー vjudge1
提出日時 2026-01-12 15:37:04
言語 C++23
(gcc 15.2.0 + boost 1.89.0)
結果
TLE  
実行時間 -
コード長 7,978 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 2,561 ms
コンパイル使用メモリ 231,740 KB
実行使用メモリ 16,200 KB
最終ジャッジ日時 2026-01-12 15:37:58
合計ジャッジ時間 53,427 ms
ジャッジサーバーID
(参考情報)
judge1 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 1
other AC * 31 TLE * 1 -- * 6
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <vector>
#include <algorithm>
#include <type_traits>
#include <cassert>

template<typename S, typename F,
        S (*op)(const S&, const S&)=S::unite,
        S (*mapping)(const F&, const S&)=F::apply,
        F (*composition)(const F&, const F&)=F::unite
>
struct LazySeg {
    int n, M, lg;
    std::vector<S> d;
    std::vector<F> lz;

    std::vector<int> _points, _rps;

    explicit LazySeg(int n_) : LazySeg(std::vector<S>(n_)) {}

    explicit LazySeg(const std::vector<S> &v) : LazySeg(v.begin(), v.end()) { }

    template<typename ForwardIt, typename std::enable_if<std::is_same<S, typename std::iterator_traits<ForwardIt>::value_type>::value, bool>::type = true>
    explicit LazySeg(ForwardIt first, ForwardIt last) {
        n = std::distance(first, last);
//        lg = 0; M = 1;
//        while (M < n) lg++, M<<=1;
        M = n;
        lg = 31 - __builtin_clz(n);
        d = std::vector<S>(2 * M);
        lz = std::vector<F>(M);
        for (int i = 0; i < n; i++) {
            d[M + i] = *first;
            ++first;
        }
        for (int i = M - 1; i >= 1; i--)
            pull(i);
    }

    S get(int x) {
        assert(0 <= x && x < n);
        x += M;
        for (int i=lg; i>=1; i--) push(x >> i);
        return d[x];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= n);
        if (l == r) return S();
        range_push(l, r);
        S sml{}, smr{};
        for (l += M, r += M; l < r; l >>= 1, r >>= 1) {
            if (l&1) sml = op(sml, d[l++]);
            if (r&1) smr = op(d[--r], smr);
        }
        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    void set(int x, S v) {
        assert(0 <= x && x < n);
        x += M;
        for (int i=lg; i>=1; i--) push(x >> i);
        d[x] = v;
        for (int i=1; i<=lg; i++) pull(x >> i);
    }

    void apply(int x, const F& f) {
        assert(0 <= x && x < n);
        x += M;
        for (int i = lg; i >= 1; i--) push(x >> i);
        d[x] = mapping(f, d[x]);
        for (int i = 1; i <= lg; i++) pull(x >> i);
    }

    void apply(int l, int r, const F& f) {
        assert(0 <= l && l <= r && r <= n);
        if (l == r) return;

        range_push(l, r); l += M; r += M;

        for (int s=l, t=r; s < t; s>>=1, t>>=1) {
            if (s & 1) apply_f(s++, f);
            if (t & 1) apply_f(--t, f);
        }

        for (int i = 1; i <= lg; i++) {
            if (((l >> i) << i) != l) pull(l >> i);
            if (((r >> i) << i) != r) pull((r - 1) >> i);
        }
    }

    // find minimal position R (l <= R < r) that g(prod(l, R+1)) == true
    // forall l <= i <= R, g(prod(l, i)) == false
    // if not found, return r
    template<typename G>
    int find_first(int l, int r, G g) {
        assert(0 <= l && r <= n && l <= r);
        _prepare_points(l, r);
        range_push(l, r);
        S acc{};
        for (int x : _points) {
            S candidate = op(acc, d[x]);
            if (g(candidate)) {
                while (x < M) {
                    push(x);
                    x <<= 1;
                    S c2 = op(acc, d[x]);
                    if (!g(c2)) {
                        acc = c2; x++;
                    }
                }
                return x - M;
            }
            acc = candidate;
        }
        return r;
    }

    template<typename G> int find_first(int l, G g) { return find_first(l, n, g); }

    // find minimal position L that g(prod(L, r)) == true
    // forall l <= i < L, g(prod(i, r)) == false
    template <class G> int find_last(int l, int r, G g) {
        assert(0 <= l && r <= n && l <= r);
        _prepare_points(l, r, true);
        range_push(l, r);
        S acc{};
        for (int x : _points) {
            S candidate = op(d[x], acc);
            if (!g(candidate)) {
                while (x < M) {
                    push(x);
                    x = (x * 2 + 1);
                    S c2 = op(d[x], acc);
                    if (g(c2)) {
                        acc = c2; x--;
                    }
                }
                return x + 1 - M;
            }
            acc = candidate;
        }
        return l;
    }

    template <class G> int find_last(int r, G g) { return find_last(0, r, g); }

private:

    void _prepare_points(int l, int r, bool reversed=false) {
        _points.clear(); _rps.clear();
        for (l += M, r += M; l < r; l >>= 1, r >>= 1) {
            if (l & 1) _points.push_back(l++);
            if (r & 1) _rps.push_back(--r);
        }
        if (reversed) {
            _rps.insert(_rps.end(), _points.rbegin(), _points.rend());
            swap(_points, _rps);
        } else {
            _points.insert(_points.end(), _rps.rbegin(), _rps.rend());
        }
    }

    void range_push(int l, int r) {
        l += M; r += M;
        for (int i=lg; i>=1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r-1) >> i);
        }
    }

    void pull(int x) {
        d[x] = op(d[x << 1], d[x<<1|1]);
    }

    void apply_f(int x, F f) {
        d[x] = mapping(f, d[x]);
        if (x < M) {
            lz[x] = composition(f, lz[x]);
            if (d[x].fail) {
                push(x);
                pull(x);
            }
        }
    }

    void push(int x) {
        if (!x) return;
        apply_f(x<<1, lz[x]);
        apply_f(x<<1|1, lz[x]);
        lz[x] = F();
    }
};

#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <cstdint>
#include <algorithm>
#include <vector>
#include <array>
#include <map>
#include <set>
#include <queue>
#include <iostream>
#include <iomanip>
#include <string>
#include <bitset>
#include <functional>
#include <string.h>
#include <numeric>

using namespace std;

typedef long long ll;
using i64 = int64_t;
using i128 = __int128_t;
using f64 = double;

const int maxn = 200050;
const ll inf = 1e9 + 1e5;

ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a%b);
}

ll safe_lcm(ll a, ll b) {
    if (a >= inf || b >= inf) return inf;
    ll g = gcd(a, b);
    ll m = a / g * b;
    if (m >= inf) return inf;
    return m;
}

struct node {

    ll s = 0;
    ll g = 0;
    int mx = 0;
    int sz = 0;
    bool fail = false;

    node() {}
    node(ll s, ll g, int mx, int sz) : s(s), g(g), mx(mx), sz(sz), fail(false) { }

    static node unite(const node &a, const node &b) {
        return {a.s + b.s, safe_lcm(a.g, b.g), max(a.mx, b.mx), a.sz + b.sz};
    }
};

struct fnode {

    int x = 0;
    int y = -1;

    fnode() {}
    fnode(ll x, int y) : x(x), y(y) { }

    static node apply(const fnode &f, const node &s) {
        node c = s;
        if (f.y != -1) {
            ll w = gcd(f.x, f.y);
            c.s = w * c.sz;
            c.g = w;
            c.mx = w;
        } else {
            if (c.sz == 1) {
                ll w = gcd(f.x, c.g);
                c.mx = c.g = c.s = w;
            } else if (c.g == inf || f.x % c.g) {
                c.fail = true;
            }
        }
        return c;
    }

    static fnode unite(const fnode &f, const fnode &g) {
        // if (f.x && g.x) cout << "fuck\n";
        if (f.y != -1) return f;
        return {gcd(f.x, g.x), g.y};
    }
};



int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    cout << fixed << setprecision(20);

    int n, Q;
    cin >> n >> Q;
    vector<node> data(n);
    for (int i=0; i<n; i++) {
        int x;
        cin >> x;
        data[i].s = data[i].g = data[i].mx = x;
        data[i].sz = 1;
    }
    LazySeg<node, fnode> tree(data);
    while (Q--) {
        int op, l, r, x;
        cin >> op >> l >> r;
        --l;
        if (op <= 2) cin >> x;
        if (op == 1) {
            tree.apply(l, r, {0, x});
        } else if (op == 2) {
            tree.apply(l, r, {x, -1});
        } else if (op == 3) {
            cout << tree.prod(l, r).mx << '\n';
        } else {
            cout << tree.prod(l, r).s << '\n';
        }
    }
}
0