結果

問題 No.650 行列木クエリ
ユーザー masayoshi361masayoshi361
提出日時 2020-11-18 22:36:00
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 394 ms / 2,000 ms
コード長 16,524 bytes
コンパイル時間 3,274 ms
コンパイル使用メモリ 213,616 KB
実行使用メモリ 54,932 KB
最終ジャッジ日時 2024-07-23 09:13:06
合計ジャッジ時間 6,083 ms
ジャッジサーバーID
(参考情報)
judge5 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,816 KB
testcase_01 AC 211 ms
14,976 KB
testcase_02 AC 371 ms
50,956 KB
testcase_03 AC 2 ms
6,940 KB
testcase_04 AC 217 ms
14,848 KB
testcase_05 AC 370 ms
50,900 KB
testcase_06 AC 2 ms
6,944 KB
testcase_07 AC 2 ms
6,944 KB
testcase_08 AC 233 ms
15,616 KB
testcase_09 AC 394 ms
54,932 KB
testcase_10 AC 2 ms
6,940 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
verify/yuki-650.test.cpp: In function 'int main()':
verify/yuki-650.test.cpp:43:18: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17' [-Wc++17-extensions]

ソースコード

diff #

#line 1 "verify/yuki-650.test.cpp"
#define PROBLEM "https://yukicoder.me/problems/no/650"
#line 1 "library/template/template.cpp"
/* #region header */

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
// types
using ll = long long;
using ull = unsigned long long;
using ld = long double;
typedef pair<ll, ll> Pl;
typedef pair<int, int> Pi;
typedef vector<ll> vl;
typedef vector<int> vi;
typedef vector<char> vc;
template <typename T>
using mat = vector<vector<T>>;
typedef vector<vector<int>> vvi;
typedef vector<vector<long long>> vvl;
typedef vector<vector<char>> vvc;
// abreviations
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rep_(i, a_, b_, a, b, ...) for (ll i = (a), max_i = (b); i < max_i; i++)
#define rep(i, ...) rep_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
#define rrep_(i, a_, b_, a, b, ...) \
    for (ll i = (b - 1), min_i = (a); i >= min_i; i--)
#define rrep(i, ...) rrep_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
#define srep(i, a, b, c) for (ll i = (a), max_i = (b); i < max_i; i += c)
#define SZ(x) ((int)(x).size())
#define pb(x) push_back(x)
#define eb(x) emplace_back(x)
#define mp make_pair
//入出力
#define print(x) cout << x << endl
template <class T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (auto& e : v) cout << e << " ";
    cout << endl;
    return os;
}
void scan(int& a) { cin >> a; }
void scan(long long& a) { cin >> a; }
void scan(char& a) { cin >> a; }
void scan(double& a) { cin >> a; }
void scan(string& a) { cin >> a; }
template <class T>
void scan(vector<T>& a) {
    for (auto& i : a) scan(i);
}
#define vsum(x) accumulate(all(x), 0LL)
#define vmax(a) *max_element(all(a))
#define vmin(a) *min_element(all(a))
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
// functions
// gcd(0, x) fails.
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }
template <class T>
bool chmax(T& a, const T& b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
bool chmin(T& a, const T& b) {
    if (b < a) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T>
T mypow(T x, ll n) {
    T ret = 1;
    while (n > 0) {
        if (n & 1) (ret *= x);
        (x *= x);
        n >>= 1;
    }
    return ret;
}
ll modpow(ll x, ll n, const ll mod) {
    ll ret = 1;
    while (n > 0) {
        if (n & 1) (ret *= x);
        (x *= x);
        n >>= 1;
        x %= mod;
        ret %= mod;
    }
    return ret;
}

uint64_t my_rand(void) {
    static uint64_t x = 88172645463325252ULL;
    x = x ^ (x << 13);
    x = x ^ (x >> 7);
    return x = x ^ (x << 17);
}
int popcnt(ull x) { return __builtin_popcountll(x); }
// graph template
template <typename T>
struct edge {
    int src, to;
    T cost;

    edge(int to, T cost) : src(-1), to(to), cost(cost) {}

    edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

    edge& operator=(const int& x) {
        to = x;
        return *this;
    }

    bool operator<(const edge<T>& r) const { return cost < r.cost; }

    operator int() const { return to; }
};
template <typename T>
using Edges = vector<edge<T>>;
template <typename T>
using WeightedGraph = vector<Edges<T>>;
using UnWeightedGraph = vector<vector<int>>;
struct Timer {
    clock_t start_time;
    void start() { start_time = clock(); }
    int lap() {
        // return x ms.
        return (clock() - start_time) * 1000 / CLOCKS_PER_SEC;
    }
};
/* #endregion*/
// constant
#define inf 1000000000ll
#define INF 4000000004000000000LL
#define endl '\n'
const long double eps = 0.000000000000001;
const long double PI = 3.141592653589793;
#line 3 "verify/yuki-650.test.cpp"
// library
#line 1 "library/graph/tree/HLD.cpp"
struct HLD {
    vector<vector<int>> G;
    vector<int> parent, depth, sub_size, v_id, id_to_v, head;
    HLD(int n)
        : G(n),
          v_id(n, -1),
          head(n),
          sub_size(n, 1),
          parent(n, -1),
          depth(n, 0),
          id_to_v(n) {}

    void add_edge(int u, int v) {
        G[u].emplace_back(v);
        G[v].emplace_back(u);
    }

    void build(int root = 0) {
        int pos = 0;
        dfs_size(root);
        head[root] = root;
        dfs_hld(root, pos);
    }

    void dfs_size(int v) {
        for (int& nv : G[v]) {
            if (nv == parent[v]) {
                nv = G[v].back();
                G[v].pop_back();
            }
        }
        for (int& nv : G[v]) {
            parent[nv] = v;
            depth[nv] = depth[v] + 1;
            dfs_size(nv);
            sub_size[v] += sub_size[nv];
            if (sub_size[nv] > sub_size[G[v][0]]) swap(nv, G[v][0]);
        }
    }

    void dfs_hld(int v, int& pos) {
        v_id[v] = pos;
        id_to_v[pos++] = v;
        for (int nv : G[v]) {
            head[nv] = (nv == G[v][0] ? head[v] : nv);
            dfs_hld(nv, pos);
        }
    }

    int lca(int u, int v) {
        while (1) {
            if (v_id[u] > v_id[v]) swap(u, v);
            if (head[u] == head[v]) return u;
            v = parent[head[v]];
        }
    }

    int distance(int u, int v) {
        return depth[u] + depth[v] - 2 * depth[lca(u, v)];
    }

    // update vertexes in [u, v] with f
    template <typename F>
    void update(int u, int v, const F& f) {
        while (1) {
            if (v_id[u] > v_id[v]) swap(u, v);
            f(max(v_id[head[v]], v_id[u]), v_id[v]);
            if (head[u] != head[v])
                v = parent[head[v]];
            else
                break;
        }
    }

    // get res for [u, v] with query q and merge each value with f
    template <typename T, typename Q, typename F>
    T query(int u, int v, T id, const Q& q, const F& f) {
        T l = id, r = id;
        while (1) {
            if (v_id[u] > v_id[v]) {
                swap(u, v);
                swap(l, r);
            }
            l = f(l, q(max(v_id[head[v]], v_id[u]), v_id[v]));
            if (head[u] != head[v])
                v = parent[head[v]];
            else
                break;
        }
        return f(l, r);
    }

    // update edges between u, v inclusive with func f
    template <typename F>
    void update_edge(int u, int v, const F& f) {
        while (1) {
            if (v_id[u] > v_id[v]) swap(u, v);
            if (head[u] != head[v]) {
                f(v_id[head[v]], v_id[v]);
                v = parent[head[v]];
            } else {
                if (u != v) f(v_id[u] + 1, v_id[v]);
                break;
            }
        }
    }

    // query for edges between u, v inclusive with query q and merge func f
    template <typename T, typename Q, typename F>
    T query_edge(int u, int v, T id, const Q& q, const F& f) {
        T l = id, r = id;
        while (1) {
            if (v_id[u] > v_id[v]) {
                swap(u, v);
                swap(l, r);
            }
            if (head[u] != head[v]) {
                l = f(l, q(v_id[head[v]], v_id[v]));
                v = parent[head[v]];
            } else {
                if (u != v) l = f(l, q(v_id[u] + 1, v_id[v]));
                break;
            }
        }
        return f(l, r);
    }
};
#line 1 "library/math/Matrix.cpp"
template <class T>
struct Matrix {
    vector<vector<T>> A;

    Matrix() {}

    Matrix(size_t n, size_t m) : A(n, vector<T>(m, 0)) {}

    Matrix(size_t n) : A(n, vector<T>(n, 0)){};

    Matrix(vector<vector<T>> a) { A = a; }

    size_t height() const { return (A.size()); }

    size_t width() const { return (A[0].size()); }

    inline const vector<T> &operator[](int k) const { return (A.at(k)); }

    inline vector<T> &operator[](int k) { return (A.at(k)); }

    static Matrix I(size_t n) {
        Matrix mat(n);
        for (int i = 0; i < n; i++) mat[i][i] = 1;
        return (mat);
    }

    Matrix &operator+=(const Matrix &B) {
        size_t n = height(), m = width();
        assert(n == B.height() && m == B.width());
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) (*this)[i][j] += B[i][j];
        return (*this);
    }

    Matrix &operator-=(const Matrix &B) {
        size_t n = height(), m = width();
        assert(n == B.height() && m == B.width());
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) (*this)[i][j] -= B[i][j];
        return (*this);
    }

    Matrix &operator*=(const Matrix &B) {
        size_t n = height(), m = B.width(), p = width();
        assert(p == B.height());
        vector<vector<T>> C(n, vector<T>(m, 0));
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                for (int k = 0; k < p; k++)
                    C[i][j] = (C[i][j] + (*this)[i][k] * B[k][j]);
        A.swap(C);
        return (*this);
    }

    Matrix &operator^=(long long k) {
        Matrix B = Matrix::I(height());
        while (k > 0) {
            if (k & 1) B *= *this;
            *this *= *this;
            k >>= 1LL;
        }
        A.swap(B.A);
        return (*this);
    }

    Matrix operator+(const Matrix &B) const { return (Matrix(*this) += B); }

    Matrix operator-(const Matrix &B) const { return (Matrix(*this) -= B); }

    Matrix operator*(const Matrix &B) const { return (Matrix(*this) *= B); }

    Matrix operator^(const long long k) const { return (Matrix(*this) ^= k); }

    Matrix pow(long long n) {
        Matrix ret = I(height());
        Matrix x = Matrix(*this);
        while (n > 0) {
            if (n & 1) (ret *= x);
            (x *= x);
            n >>= 1;
        }
        return ret;
    }

    friend ostream &operator<<(ostream &os, Matrix &p) {
        size_t n = p.height(), m = p.width();
        for (int i = 0; i < n; i++) {
            os << "[";
            for (int j = 0; j < m; j++) {
                os << p[i][j] << (j + 1 == m ? "]\n" : ",");
            }
        }
        return (os);
    }

    T determinant() {
        Matrix B(*this);
        assert(width() == height());
        T ret = 1;
        for (int i = 0; i < width(); i++) {
            int idx = -1;
            for (int j = i; j < width(); j++) {
                if (B[j][i] != 0) idx = j;
            }
            if (idx == -1) return (0);
            if (i != idx) {
                ret *= -1;
                swap(B[i], B[idx]);
            }
            ret *= B[i][i];
            T vv = B[i][i];
            for (int j = 0; j < width(); j++) {
                B[i][j] /= vv;
            }
            for (int j = i + 1; j < width(); j++) {
                T a = B[j][i];
                for (int k = 0; k < width(); k++) {
                    B[j][k] -= B[i][k] * a;
                }
            }
        }
        return (ret);
    }
};
#line 1 "library/mod/modint.cpp"
template <int mod>
struct modint {
    int x;

    modint() : x(0) {}

    modint(long long y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

    modint& operator+=(const modint& p) {
        if ((x += p.x) >= mod) x -= mod;
        return *this;
    }

    modint& operator-=(const modint& p) {
        if ((x += mod - p.x) >= mod) x -= mod;
        return *this;
    }

    modint& operator*=(const modint& p) {
        x = (int)(1LL * x * p.x % mod);
        return *this;
    }

    modint& operator/=(const modint& p) {
        *this *= p.inverse();
        return *this;
    }

    modint operator-() const { return modint(-x); }

    modint operator+(const modint& p) const { return modint(*this) += p; }

    modint operator-(const modint& p) const { return modint(*this) -= p; }

    modint operator*(const modint& p) const { return modint(*this) *= p; }

    modint operator/(const modint& p) const { return modint(*this) /= p; }

    bool operator==(const modint& p) const { return x == p.x; }

    bool operator!=(const modint& p) const { return x != p.x; }

    modint inverse() const {
        int a = x, b = mod, u = 1, v = 0, t;
        while (b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return modint(u);
    }

    modint pow(int64_t n) const {
        modint ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }

    friend ostream& operator<<(ostream& os, const modint& p) {
        return os << p.x;
    }

    friend istream& operator>>(istream& is, modint& a) {
        long long t;
        is >> t;
        a = modint<mod>(t);
        return (is);
    }

    static int get_mod() { return mod; }
};
#line 1 "library/structure/segtree/SegmentTree.cpp"
/**
 * @brief Segment Tree
 * @docs docs/segmenttree.md
 */
template <typename Monoid>
struct SegmentTree {
    using F = function<Monoid(Monoid, Monoid)>;

    int sz;
    vector<Monoid> seg;

    const F f;
    const Monoid M1;

    SegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
        sz = 1;
        while (sz < n) sz <<= 1;
        seg.assign(2 * sz, M1);
    }

    void set(int k, const Monoid &x) { seg[k + sz] = x; }

    void build() {
        for (int k = sz - 1; k > 0; k--) {
            seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
        }
    }

    void update(int k, const Monoid &x) {
        k += sz;
        seg[k] = x;
        while (k >>= 1) {
            seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
        }
    }

    Monoid query(int a, int b) {
        Monoid L = M1, R = M1;
        for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
            if (a & 1) L = f(L, seg[a++]);
            if (b & 1) R = f(seg[--b], R);
        }
        return f(L, R);
    }

    Monoid operator[](const int &k) const { return seg[k + sz]; }

    template <typename C>
    int find_subtree(int a, const C &check, Monoid &M, bool type) {
        while (a < sz) {
            Monoid nxt =
                type ? f(seg[2 * a + type], M) : f(M, seg[2 * a + type]);
            if (check(nxt))
                a = 2 * a + type;
            else
                M = nxt, a = 2 * a + 1 - type;
        }
        return a - sz;
    }

    // check(seg[i])を満たす最小のb<=iを返す.なければ-1
    template <typename C>
    int find_first(int a, const C &check) {
        Monoid L = M1;
        if (a <= 0) {
            if (check(f(L, seg[1]))) return find_subtree(1, check, L, false);
            return -1;
        }
        int b = sz;
        for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
            if (a & 1) {
                Monoid nxt = f(L, seg[a]);
                if (check(nxt)) return find_subtree(a, check, L, false);
                L = nxt;
                ++a;
            }
        }
        return -1;
    }

    // check(seg[i])を満たす最小のi<bを返す.なければ-1
    template <typename C>
    int find_last(int b, const C &check) {
        Monoid R = M1;
        if (b >= sz) {
            if (check(f(seg[1], R))) return find_subtree(1, check, R, true);
            return -1;
        }
        int a = sz;
        for (b += sz; a < b; a >>= 1, b >>= 1) {
            if (b & 1) {
                Monoid nxt = f(seg[--b], R);
                if (check(nxt)) return find_subtree(b, check, R, true);
                R = nxt;
            }
        }
        return -1;
    }
};
#line 8 "verify/yuki-650.test.cpp"
using mint = modint<1000000007>;
using mmat = Matrix<mint>;

int main() {
    int n, q;
    cin >> n;
    HLD hld(n);
    vector<Pi> etov(n - 1);
    rep(i, n - 1) {
        int a, b;
        cin >> a >> b;
        hld.add_edge(a, b);
        etov[i] = mp(a, b);
    }
    cin >> q;
    SegmentTree<mmat> seg(
        n, [&](mmat a, mmat b) { return a * b; }, mmat::I(2));
    hld.build();
    rep(_, q) {
        char t;
        cin >> t;
        if (t == 'g') {
            int u, v;
            cin >> u >> v;
            mmat res = hld.query_edge(
                u, v, mmat::I(2),
                [&](int a, int b) { return seg.query(a, b + 1); },
                [&](mmat a, mmat b) { return b * a; });
            rep(r, 2) {
                rep(c, 2) { cout << res[r][c] << ' '; }
            }
            cout << endl;
        } else {
            int i, a, b, c, d;
            cin >> i >> a >> b >> c >> d;
            auto [u, v] = etov[i];
            hld.update_edge(u, v, [&](int l, int r) {
                return seg.update(l, mmat({{a, b}, {c, d}}));
            });
        }
    }
}
0