結果

問題 No.2470 Gemini Tree(Ver.Jadeite)
ユーザー 👑 rin204rin204
提出日時 2023-07-30 17:08:39
言語 C++23
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 408 ms / 5,000 ms
コード長 22,192 bytes
コンパイル時間 7,139 ms
コンパイル使用メモリ 286,228 KB
実行使用メモリ 30,164 KB
最終ジャッジ日時 2023-09-19 06:04:40
合計ジャッジ時間 21,931 ms
ジャッジサーバーID
(参考情報)
judge15 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,380 KB
testcase_01 AC 2 ms
4,380 KB
testcase_02 AC 2 ms
4,384 KB
testcase_03 AC 2 ms
4,380 KB
testcase_04 AC 1 ms
4,380 KB
testcase_05 AC 1 ms
4,380 KB
testcase_06 AC 406 ms
30,036 KB
testcase_07 AC 408 ms
30,016 KB
testcase_08 AC 378 ms
30,044 KB
testcase_09 AC 392 ms
30,108 KB
testcase_10 AC 382 ms
30,092 KB
testcase_11 AC 394 ms
30,092 KB
testcase_12 AC 398 ms
30,124 KB
testcase_13 AC 403 ms
30,104 KB
testcase_14 AC 391 ms
30,088 KB
testcase_15 AC 359 ms
30,088 KB
testcase_16 AC 350 ms
30,040 KB
testcase_17 AC 310 ms
30,096 KB
testcase_18 AC 349 ms
30,072 KB
testcase_19 AC 368 ms
30,112 KB
testcase_20 AC 368 ms
30,040 KB
testcase_21 AC 361 ms
30,044 KB
testcase_22 AC 366 ms
30,140 KB
testcase_23 AC 351 ms
30,164 KB
testcase_24 AC 373 ms
30,048 KB
testcase_25 AC 386 ms
30,100 KB
testcase_26 AC 360 ms
30,096 KB
testcase_27 AC 380 ms
30,100 KB
testcase_28 AC 352 ms
30,100 KB
testcase_29 AC 375 ms
30,028 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

// start A.cpp
// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;

using ll  = long long;
using ull = unsigned long long;
template <class T>
using pq = priority_queue<T>;
template <class T>
using qp = priority_queue<T, vector<T>, greater<T>>;
#define vec(T, A, ...) vector<T> A(__VA_ARGS__);
#define vvec(T, A, h, ...) vector<vector<T>> A(h, vector<T>(__VA_ARGS__));
#define vvvec(T, A, h1, h2, ...) vector<vector<vector<T>>> A(h1, vector<vector<T>>(h2, vector<T>(__VA_ARGS__)));

#ifndef RIN__LOCAL
#define endl "\n"
#endif
#define spa ' '
#define len(A) A.size()
#define all(A) begin(A), end(A)

#define fori1(a) for (ll _ = 0; _ < (a); _++)
#define fori2(i, a) for (ll i = 0; i < (a); i++)
#define fori3(i, a, b) for (ll i = (a); i < (b); i++)
#define fori4(i, a, b, c) for (ll i = (a); ((c) > 0 || i > (b)) && ((c) < 0 || i < (b)); i += (c))
#define overload4(a, b, c, d, e, ...) e
#define fori(...) overload4(__VA_ARGS__, fori4, fori3, fori2, fori1)(__VA_ARGS__)

vector<char> stoc(string &S) {
    int n = S.size();
    vector<char> ret(n);
    for (int i = 0; i < n; i++) ret[i] = S[i];
    return ret;
}

#define INT(...)                                                                                                                                                                                       \
    int __VA_ARGS__;                                                                                                                                                                                   \
    inp(__VA_ARGS__);
#define LL(...)                                                                                                                                                                                        \
    ll __VA_ARGS__;                                                                                                                                                                                    \
    inp(__VA_ARGS__);
#define STRING(...)                                                                                                                                                                                    \
    string __VA_ARGS__;                                                                                                                                                                                \
    inp(__VA_ARGS__);
#define CHAR(...)                                                                                                                                                                                      \
    char __VA_ARGS__;                                                                                                                                                                                  \
    inp(__VA_ARGS__);
#define VEC(T, A, n)                                                                                                                                                                                   \
    vector<T> A(n);                                                                                                                                                                                    \
    inp(A);
#define VVEC(T, A, n, m)                                                                                                                                                                               \
    vector<vector<T>> A(n, vector<T>(m));                                                                                                                                                              \
    inp(A);

const ll MOD1 = 1000000007;
const ll MOD9 = 998244353;

template <class T>
auto min(const T &a) {
    return *min_element(all(a));
}
template <class T>
auto max(const T &a) {
    return *max_element(all(a));
}
template <class T, class S>
auto clamp(T &a, const S &l, const S &r) {
    return (a > r ? r : a < l ? l : a);
}
template <class T, class S>
inline bool chmax(T &a, const S &b) {
    return (a < b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chmin(T &a, const S &b) {
    return (a > b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chclamp(T &a, const S &l, const S &r) {
    auto b = clamp(a, l, r);
    return (a != b ? a = b, 1 : 0);
}

void FLUSH() {
    cout << flush;
}
void print() {
    cout << endl;
}
template <class Head, class... Tail>
void print(Head &&head, Tail &&...tail) {
    cout << head;
    if (sizeof...(Tail)) cout << spa;
    print(forward<Tail>(tail)...);
}
template <typename T>
void print(vector<T> &A) {
    int n = A.size();
    for (int i = 0; i < n; i++) {
        cout << A[i];
        if (i != n - 1) cout << ' ';
    }
    cout << endl;
}
template <typename T>
void print(vector<vector<T>> &A) {
    for (auto &row : A) print(row);
}
template <typename T, typename S>
void print(pair<T, S> &A) {
    cout << A.first << spa << A.second << endl;
}
template <typename T, typename S>
void print(vector<pair<T, S>> &A) {
    for (auto &row : A) print(row);
}
template <typename T, typename S>
void prisep(vector<T> &A, S sep) {
    int n = A.size();
    for (int i = 0; i < n; i++) {
        cout << A[i];
        if (i != n - 1) cout << sep;
    }
    cout << endl;
}
template <typename T, typename S>
void priend(T A, S end) {
    cout << A << end;
}
template <typename T>
void priend(T A) {
    priend(A, spa);
}
template <typename T, typename S>
bool printif(bool f, T A, S B) {
    if (f)
        print(A);
    else
        print(B);
    return f;
}
template <class... T>
void inp(T &...a) {
    (cin >> ... >> a);
}
template <typename T>
void inp(vector<T> &A) {
    for (auto &a : A) cin >> a;
}
template <typename T>
void inp(vector<vector<T>> &A) {
    for (auto &row : A) inp(row);
}
template <typename T, typename S>
void inp(pair<T, S> &A) {
    inp(A.first, A.second);
}
template <typename T, typename S>
void inp(vector<pair<T, S>> &A) {
    for (auto &row : A) inp(row.first, row.second);
}

template <typename T>
T sum(vector<T> &A) {
    T tot = 0;
    for (auto a : A) tot += a;
    return tot;
}

template <typename T>
vector<T> compression(vector<T> X) {
    sort(all(X));
    X.erase(unique(all(X)), X.end());
    return X;
}

vector<vector<int>> read_edges(int n, int m, bool direct = false, int indexed = 1) {
    vector<vector<int>> edges(n, vector<int>());
    for (int i = 0; i < m; i++) {
        INT(u, v);
        u -= indexed;
        v -= indexed;
        edges[u].push_back(v);
        if (!direct) edges[v].push_back(u);
    }
    return edges;
}
vector<vector<int>> read_tree(int n, int indexed = 1) {
    return read_edges(n, n - 1, false, indexed);
}
template <typename T>
vector<vector<pair<int, T>>> read_wedges(int n, int m, bool direct = false, int indexed = 1) {
    vector<vector<pair<int, T>>> edges(n, vector<pair<int, T>>());
    for (int i = 0; i < m; i++) {
        INT(u, v);
        T w;
        inp(w);
        u -= indexed;
        v -= indexed;
        edges[u].push_back({v, w});
        if (!direct) edges[v].push_back({u, w});
    }
    return edges;
}
template <typename T>
vector<vector<pair<int, T>>> read_wtree(int n, int indexed = 1) {
    return read_wedges<T>(n, n - 1, false, indexed);
}

inline bool yes(bool f = true) {
    cout << (f ? "yes" : "no") << endl;
    return f;
}
inline bool Yes(bool f = true) {
    cout << (f ? "Yes" : "No") << endl;
    return f;
}
inline bool YES(bool f = true) {
    cout << (f ? "YES" : "NO") << endl;
    return f;
}

inline bool no(bool f = true) {
    cout << (!f ? "yes" : "no") << endl;
    return f;
}
inline bool No(bool f = true) {
    cout << (!f ? "Yes" : "No") << endl;
    return f;
}
inline bool NO(bool f = true) {
    cout << (!f ? "YES" : "NO") << endl;
    return f;
}

// start atcoder/lazysegtree.hpp
#ifndef ATCODER_LAZYSEGTREE_HPP
#define ATCODER_LAZYSEGTREE_HPP 1

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

// start atcoder/internal_bit.hpp
#ifndef ATCODER_INTERNAL_BITOP_HPP
#define ATCODER_INTERNAL_BITOP_HPP 1

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

    namespace internal {

        // @param n `0 <= n`
        // @return minimum non-negative `x` s.t. `n <= 2**x`
        int ceil_pow2(int n) {
            int x = 0;
            while ((1U << x) < (unsigned int)(n)) x++;
            return x;
        }

        // @param n `1 <= n`
        // @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
        constexpr int bsf_constexpr(unsigned int n) {
            int x = 0;
            while (!(n & (1 << x))) x++;
            return x;
        }

        // @param n `1 <= n`
        // @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
        int bsf(unsigned int n) {
#ifdef _MSC_VER
            unsigned long index;
            _BitScanForward(&index, n);
            return index;
#else
            return __builtin_ctz(n);
#endif
        }

    } // namespace internal

} // namespace atcoder

#endif // ATCODER_INTERNAL_BITOP_HPP

// end atcoder/internal_bit.hpp
// restart atcoder/lazysegtree.hpp

namespace atcoder {

    template <class S, S (*op)(S, S), S (*e)(), class F, S (*mapping)(F, S), F (*composition)(F, F), F (*id)()>
    struct lazy_segtree {
      public:
        lazy_segtree() : lazy_segtree(0) {}
        explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
        explicit lazy_segtree(const std::vector<S> &v) : _n(int(v.size())) {
            log  = internal::ceil_pow2(_n);
            size = 1 << log;
            d    = std::vector<S>(2 * size, e());
            lz   = std::vector<F>(size, id());
            for (int i = 0; i < _n; i++) d[size + i] = v[i];
            for (int i = size - 1; i >= 1; i--) {
                update(i);
            }
        }

        void set(int p, S x) {
            assert(0 <= p && p < _n);
            p += size;
            for (int i = log; i >= 1; i--) push(p >> i);
            d[p] = x;
            for (int i = 1; i <= log; i++) update(p >> i);
        }

        S get(int p) {
            assert(0 <= p && p < _n);
            p += size;
            for (int i = log; i >= 1; i--) push(p >> i);
            return d[p];
        }

        S prod(int l, int r) {
            assert(0 <= l && l <= r && r <= _n);
            if (l == r) return e();

            l += size;
            r += size;

            for (int i = log; i >= 1; i--) {
                if (((l >> i) << i) != l) push(l >> i);
                if (((r >> i) << i) != r) push((r - 1) >> i);
            }

            S sml = e(), smr = e();
            while (l < r) {
                if (l & 1) sml = op(sml, d[l++]);
                if (r & 1) smr = op(d[--r], smr);
                l >>= 1;
                r >>= 1;
            }

            return op(sml, smr);
        }

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

        void apply(int p, F f) {
            assert(0 <= p && p < _n);
            p += size;
            for (int i = log; i >= 1; i--) push(p >> i);
            d[p] = mapping(f, d[p]);
            for (int i = 1; i <= log; i++) update(p >> i);
        }
        void apply(int l, int r, F f) {
            assert(0 <= l && l <= r && r <= _n);
            if (l == r) return;

            l += size;
            r += size;

            for (int i = log; i >= 1; i--) {
                if (((l >> i) << i) != l) push(l >> i);
                if (((r >> i) << i) != r) push((r - 1) >> i);
            }

            {
                int l2 = l, r2 = r;
                while (l < r) {
                    if (l & 1) all_apply(l++, f);
                    if (r & 1) all_apply(--r, f);
                    l >>= 1;
                    r >>= 1;
                }
                l = l2;
                r = r2;
            }

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

        template <bool (*g)(S)>
        int max_right(int l) {
            return max_right(l, [](S x) { return g(x); });
        }
        template <class G>
        int max_right(int l, G g) {
            assert(0 <= l && l <= _n);
            assert(g(e()));
            if (l == _n) return _n;
            l += size;
            for (int i = log; i >= 1; i--) push(l >> i);
            S sm = e();
            do {
                while (l % 2 == 0) l >>= 1;
                if (!g(op(sm, d[l]))) {
                    while (l < size) {
                        push(l);
                        l = (2 * l);
                        if (g(op(sm, d[l]))) {
                            sm = op(sm, d[l]);
                            l++;
                        }
                    }
                    return l - size;
                }
                sm = op(sm, d[l]);
                l++;
            } while ((l & -l) != l);
            return _n;
        }

        template <bool (*g)(S)>
        int min_left(int r) {
            return min_left(r, [](S x) { return g(x); });
        }
        template <class G>
        int min_left(int r, G g) {
            assert(0 <= r && r <= _n);
            assert(g(e()));
            if (r == 0) return 0;
            r += size;
            for (int i = log; i >= 1; i--) push((r - 1) >> i);
            S sm = e();
            do {
                r--;
                while (r > 1 && (r % 2)) r >>= 1;
                if (!g(op(d[r], sm))) {
                    while (r < size) {
                        push(r);
                        r = (2 * r + 1);
                        if (g(op(d[r], sm))) {
                            sm = op(d[r], sm);
                            r--;
                        }
                    }
                    return r + 1 - size;
                }
                sm = op(d[r], sm);
            } while ((r & -r) != r);
            return 0;
        }

      private:
        int _n, size, log;
        std::vector<S> d;
        std::vector<F> lz;

        void update(int k) {
            d[k] = op(d[2 * k], d[2 * k + 1]);
        }
        void all_apply(int k, F f) {
            d[k] = mapping(f, d[k]);
            if (k < size) lz[k] = composition(f, lz[k]);
        }
        void push(int k) {
            all_apply(2 * k, lz[k]);
            all_apply(2 * k + 1, lz[k]);
            lz[k] = id();
        }
    };

} // namespace atcoder

#endif // ATCODER_LAZYSEGTREE_HPP

// end atcoder/lazysegtree.hpp
// restart A.cpp
// start tree/HLD.hpp

struct HLD {
    int n, path;
    vector<vector<int>> edges;
    vector<int> siz;
    vector<int> par;
    vector<int> depth;
    vector<int> path_ind;
    vector<int> path_root;
    vector<int> heavy_child;
    vector<bool> isheavy;
    vector<int> L;
    vector<int> R;

    HLD(int n) : n(n) {
        edges.resize(n);
        siz.assign(n, -1);
        par.assign(n, -1);
        depth.assign(n, -1);
        path_ind.assign(n, -1);
        heavy_child.assign(n, -1);
        isheavy.assign(n, false);
        L.assign(n, -1);
        R.assign(n, -1);
    }

    void read_edges(int indexed = 1) {
        int u, v;
        for (int i = 0; i < n - 1; i++) {
            cin >> u >> v;
            u -= indexed;
            v -= indexed;
            edges[u].push_back(v);
            edges[v].push_back(u);
        }
    }

    void add_edge(int u, int v) {
        edges[u].push_back(v);
        edges[v].push_back(u);
    }

    void build(int root = 0) {
        depth[root] = 0;
        stack<int> st;
        vector<int> route;
        st.push(root);
        route.push_back(root);
        while (!st.empty()) {
            int pos = st.top();
            st.pop();
            for (auto npos : edges[pos]) {
                if (depth[npos] == -1) {
                    depth[npos] = depth[pos] + 1;
                    par[npos]   = pos;
                    st.push(npos);
                    route.push_back(npos);
                }
            }
        }
        reverse(route.begin(), route.end());
        for (auto pos : route) {
            siz[pos] = 1;
            int ma   = -1;
            for (auto npos : edges[pos]) {
                if (depth[npos] > depth[pos]) siz[pos] += siz[npos];
                if (siz[npos] > ma) {
                    ma               = siz[npos];
                    heavy_child[pos] = npos;
                }
            }
            if (heavy_child[pos] != -1) isheavy[heavy_child[pos]] = true;
        }
        isheavy[root] = true;

        path = 0;
        st.push(~root);
        st.push(root);
        path_root.push_back(root);
        int cc = 0;
        while (!st.empty()) {
            int pos = st.top();
            st.pop();
            if (pos >= 0) {
                L[pos] = cc++;
                if (!isheavy[pos]) {
                    path++;
                    path_root.push_back(pos);
                }
                path_ind[pos] = path;
                for (auto npos : edges[pos]) {
                    if (npos == par[pos] || npos == heavy_child[pos]) continue;
                    st.push(~npos);
                    st.push(npos);
                }
                if (heavy_child[pos] != -1) {
                    int npos = heavy_child[pos];
                    st.push(~npos);
                    st.push(npos);
                }
            } else {
                pos    = ~pos;
                R[pos] = cc;
            }
        }
    }

    vector<pair<int, int>> get_path(int u, int v) {
        vector<int> ll;
        vector<int> rr;
        ll.push_back(u);
        rr.push_back(v);
        while (path_ind[u] != path_ind[v]) {
            if (depth[path_root[path_ind[u]]] >= depth[path_root[path_ind[v]]]) {
                u = path_root[path_ind[u]];
                ll.push_back(u);
                u = par[u];
                ll.push_back(u);
            } else {
                v = path_root[path_ind[v]];
                rr.push_back(v);
                v = par[v];
                rr.push_back(v);
            }
        }
        reverse(rr.begin(), rr.end());
        ll.insert(ll.end(), rr.begin(), rr.end());
        int n = ll.size();
        vector<pair<int, int>> res(n / 2);
        for (int i = 0; i < n; i += 2) {
            res[i / 2] = {ll[i], ll[i + 1]};
        }
        return res;
    }

    int lca(int u, int v) {
        while (path_ind[u] != path_ind[v]) {
            if (depth[path_root[path_ind[u]]] >= depth[path_root[path_ind[v]]])
                u = par[path_root[path_ind[u]]];
            else
                v = par[path_root[path_ind[v]]];
        }
        return (depth[u] <= depth[v]) ? u : v;
    }

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

    template <typename T>
    vector<T> reorder(vector<T> &A, bool rev = false) {
        assert(n == A.size());
        vector<T> ret(n);
        for (int i = 0; i < n; i++) {
            ret[L[i]] = A[i];
        }
        if (rev) reverse(ret.begin(), ret.end());
        return ret;
    }
};

// end tree/HLD.hpp
// restart A.cpp

const ll inf = 1LL << 60;
ll op(ll l, ll r) {
    return l < r ? l : r;
}
ll e() {
    return inf;
}
ll mapping(ll f, ll x) {
    return f + x;
}
ll composition(ll f, ll g) {
    return f + g;
}
ll id() {
    return 0;
}

void solve() {
    INT(n);
    STRING(S);
    int g = 0;
    int b = 0;
    for (auto s : S) {
        if (s == 'G')
            g++;
        else
            b++;
    }
    if (g > b) {
        swap(g, b);
        fori(i, n) {
            S[i] = S[i] ^ 'B' ^ 'G';
        }
    }

    if (g == 0) {
        fori(n - 1) {
            INT(u, v, w);
        }
        INT(Q);
        fori(Q) {
            INT(e, a);
            print(0);
        }
        return;
    }

    VVEC(ll, E, n - 1, 3);
    using P = pair<int, ll>;
    vvec(P, edges, n);
    for (auto &tmp : E) {
        tmp[0]--;
        tmp[1]--;
        edges[tmp[0]].emplace_back(tmp[1], tmp[2]);
        edges[tmp[1]].emplace_back(tmp[0], tmp[2]);
    }

    int cent = -1;
    vec(int, siz, n, 1);
    vec(int, gc, n, 0);
    auto dfs = [&](auto &&self, int pos, int bpos) -> void {
        bool ok  = true;
        siz[pos] = 1;
        gc[pos]  = 0;
        if (S[pos] == 'G') gc[pos]++;
        for (auto [npos, _] : edges[pos]) {
            if (npos == bpos) continue;
            self(self, npos, pos);
            siz[pos] += siz[npos];
            gc[pos] += gc[npos];
            if (siz[npos] * 2 > n) ok = false;
        }
        if ((n - siz[pos]) * 2 > n) ok = false;
        if (ok) cent = pos;
    };

    dfs(dfs, 0, -1);

    HLD hld(n);
    for (auto tmp : E) hld.add_edge(tmp[0], tmp[1]);

    int cc = cent;
    hld.build(cent);
    dfs(dfs, cent, -1);
    cent = cc;

    vec(ll, ini, n, 0);
    fori(i, n) {
        if (siz[i] != g) ini[hld.L[i]] = inf;
    }
    atcoder::lazy_segtree<ll, op, e, ll, mapping, composition, id> seg(ini);

    vec(int, upp, n, -1);
    stack<int> st;
    st.push(cent);
    upp[cent] = cent;
    while (!st.empty()) {
        int pos = st.top();
        st.pop();
        for (auto [npos, _] : edges[pos]) {
            if (upp[npos] == -1) {
                upp[npos] = upp[pos];
                if (siz[pos] > g) upp[npos] = npos;
                st.push(npos);
            }
        }
    }

    auto add = [&](int u, int v, ll w) {
        if (hld.depth[u] < hld.depth[v]) swap(u, v);
        ll x = w * gc[u];
        seg.apply(0, n, x);

        x *= -1;
        x += w * min(g - gc[u], siz[u] - gc[u]);

        u = upp[u];

        seg.apply(hld.L[u], hld.R[u], x);
    };

    for (auto tmp : E) {
        add(tmp[0], tmp[1], tmp[2]);
    }

    INT(Q);
    fori(Q) {
        LL(e, a);
        e--;
        add(E[e][0], E[e][1], a);
        print(seg.all_prod());
    }
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    // cout << fixed << setprecision(12);
    int t;
    t = 1;
    // cin >> t;
    while (t--) solve();
    return 0;
}

// end A.cpp
0