답안 #1093608

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1093608 2024-09-27T06:43:43 Z CDuong Inside information (BOI21_servers) C++
80 / 100
265 ms 28680 KB
/*
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx2,fma,bmi,bmi2,sse4.2,popcnt,lzcnt")
*/

#include <bits/stdc++.h>
#define taskname ""
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define i64 long long
#define isz(x) (int)x.size()
using namespace std;

template<bool ALLOW_NON_PREFIX_QUERY, class T, class F, class I>
struct fenwick_tree{
    int n;
    vector<T> data;
    F TT;
    T T_id;
    I Tinv;
    fenwick_tree(F TT, T T_id, I Tinv): TT(TT), T_id(T_id), Tinv(Tinv){ }
    fenwick_tree &operator=(const fenwick_tree &fw){
        n = fw.n;
        data = fw.data;
    }
    // O(n)
    void build(int n){
        assert(n >= 0);
        this->n = n;
        data.assign(n, T_id);
    }
    // O(n)
    void build(int n, T x){
        assert(n >= 0);
        this->n = n;
        data.assign(n, x);
        for(auto i = 1; i <= n; ++ i) if(i + (i & -i) <= n) data[i + (i & -i) - 1] = TT(data[i + (i & -i) - 1], data[i - 1]);
    }
    // O(n)
    template<class U>
    void build(const vector<U> &a){
        n = (int)a.size();
        data.resize(n);
        copy(a.begin(), a.end(), data.begin());
        for(auto i = 1; i <= n; ++ i) if(i + (i & -i) <= n) data[i + (i & -i) - 1] = TT(data[i + (i & -i) - 1], data[i - 1]);
    }
    // O(log(n))
    void update(int p, T x){
        assert(0 <= p && p < n);
        for(++ p; p <= n; p += p & -p) data[p - 1] = TT(data[p - 1], x);
    }
    // O(log(n))
    void set(int p, T x){
        update(p, TT(x, Tinv(query(p))));
    }
    // O(log(n))
    T prefix(int r) const{
        assert(0 <= r && r <= n);
        T s = T_id;
        for(; r > 0; r -= r & -r) s = TT(s, data[r - 1]);
        return s;
    }
    // O(log(n))
    T query(int l, int r) const{
        static_assert(ALLOW_NON_PREFIX_QUERY);
        assert(0 <= l && l <= r && r <= n);
        if(l == r) return T_id;
        T sum_minus = T_id, sum_plus = T_id;
        for(; l < r; r -= r & -r) sum_plus = TT(sum_plus, data[r - 1]);
        for(; r < l; l -= l & -l) sum_minus = TT(sum_minus, data[l - 1]);
        return TT(sum_plus, Tinv(sum_minus));
    }
    // O(log(n))
    T query(int p) const{
        static_assert(ALLOW_NON_PREFIX_QUERY);
        return query(p, p + 1);
    }
    // O(log(n))
    T query_all() const{
        return prefix(n);
    }
    // pred(sum[0, r)) is T, T, ..., T, F, F, ..., F, returns max r with T
    // O(log(n))
    int max_pref(auto pred) const{
        assert(pred(T_id));
        int p = 0;
        T sum = T_id;
        for(auto i = __lg(n + 1); i >= 0; -- i) if(p + (1 << i) <= n && pred(TT(sum, data[p + (1 << i) - 1]))){
            sum = TT(sum, data[p + (1 << i) - 1]);
            p += 1 << i;
        }
        return p;
    }
    template<class output_stream>
    friend output_stream &operator<<(output_stream &out, const fenwick_tree &fw){
        out << "{";
        for(auto i = 0; i < fw.n; ++ i){
            out << fw.query(i);
            if(i != fw.n - 1) out << ", ";
        }
        return out << '}';
    }
};

template<class T, class F, class I>
auto make_fenwick_tree(F TT, T T_id, I Tinv){
    return fenwick_tree<true, T, F, I>(TT, T_id, Tinv);
}
template<class T>
auto make_fenwick_tree_sum(){
    return fenwick_tree<true, T, plus<>, negate<>>(plus<>(), T{0}, negate<>());
}
template<class T>
auto make_fenwick_tree_product(){
    auto inverse = [](const T &x){ return 1 / x; };
    return fenwick_tree<true, T, multiplies<>, decltype(inverse)>(multiplies<>(), T{1}, inverse);
}
template<class T>
auto make_fenwick_tree_min(){
    auto TT = [&](const T &x, const T &y)->T{ return min(x, y); };
    return fenwick_tree<false, T, decltype(TT), negate<>>(TT, numeric_limits<T>::max(), negate<>());
}
template<class T>
auto make_fenwick_tree_max(){
    auto TT = [&](const T &x, const T &y)->T{ return max(x, y); };
    return fenwick_tree<false, T, decltype(TT), negate<>>(TT, numeric_limits<T>::max(), negate<>());
}

template<class T>
struct graph{
    using Weight_t = T;
    struct Edge_t{
        int from, to;
        T cost;
    };
    int n;
    vector<Edge_t> edge;
    vector<vector<int>> adj;
    function<bool(int)> ignore;
    graph(int n = 1): n(n), adj(n){
        assert(n >= 1);
    }
    graph(const vector<vector<int>> &adj, bool undirected = true): n((int)adj.size()), adj(n){
        assert(n >= 1);
        if(undirected){
            for(auto u = 0; u < n; ++ u) for(auto v: adj[u]) if(u < v) link(u, v);
        }
        else for(auto u = 0; u < n; ++ u) for(auto v: adj[u]) orient(u, v);
    }
    graph(const vector<vector<pair<int, T>>> &adj, bool undirected = true): n((int)adj.size()), adj(n){
        assert(n >= 1);
        if(undirected){
            for(auto u = 0; u < n; ++ u) for(auto [v, w]: adj[u]) if(u < v) link(u, v, w);
        }
        else for(auto u = 0; u < n; ++ u) for(auto [v, w]: adj[u]) orient(u, v, w);
    }
    graph(int n, vector<array<int, 2>> &edge, bool undirected = true): n(n), adj(n){
        assert(n >= 1);
        for(auto [u, v]: edge) undirected ? link(u, v) : orient(u, v);
    }
    graph(int n, vector<tuple<int, int, T>> &edge, bool undirected = true): n(n), adj(n){
        assert(n >= 1);
        for(auto [u, v, w]: edge) undirected ? link(u, v, w) : orient(u, v, w);
    }
    int add_vertex(){
        adj.emplace_back();
        return n ++;
    }
    int operator()(int u, int id) const{
        #ifdef LOCAL
        assert(0 <= id && id < (int)edge.size());
        assert(edge[id].from == u || edge[id].to == u);
        #endif
        return u ^ edge[id].from ^ edge[id].to;
    }
    int link(int u, int v, T w = {}){ // insert an undirected edge
        int id = (int)edge.size();
        adj[u].push_back(id), adj[v].push_back(id), edge.push_back({u, v, w});
        return id;
    }
    int orient(int u, int v, T w = {}){ // insert a directed edge
        int id = (int)edge.size();
        adj[u].push_back(id), edge.push_back({u, v, w});
        return id;
    }
    vector<int> neighbor(int u, int exclude = -1) const{
        vector<int> res;
        for(auto id: adj[u]){
            if(id == exclude || ignore && ignore(id)) continue;
            res.push_back(operator()(u, id));
        }
        return res;
    }
    void clear(){
        for(auto [u, v, w]: edge){
            adj[u].clear();
            adj[v].clear();
        }
        edge.clear();
        ignore = {};
    }
    graph transpose() const{ // the transpose of the directed graph
        graph res(n);
        for(auto id = 0; id < (int)edge.size(); ++ id){
            if(ignore && ignore(id)) continue;
            res.orient(edge[id].to, edge[id].from, edge[id].cost);
        }
        return res;
    }
    int degree(int u) const{ // the degree (outdegree if directed) of u (without the ignoration rule)
        return (int)adj[u].size();
    }
    // The adjacency list is sorted for each vertex.
    vector<vector<int>> get_adjacency_list() const{
        vector<vector<int>> res(n);
        for(auto u = 0; u < n; ++ u) for(auto id: adj[u]){
            if(ignore && ignore(id)) continue;
            res[(*this)(u, id)].push_back(u);
        }
        return res;
    }
    void set_ignoration_rule(const function<bool(int)> &f){
        ignore = f;
    }
    void reset_ignoration_rule(){
        ignore = nullptr;
    }
    friend ostream &operator<<(ostream &out, const graph &g){
        for(auto id = 0; id < (int)g.edge.size(); ++ id){
            if(g.ignore && g.ignore(id)) continue;
            auto &e = g.edge[id];
            out << "{" << e.from << ", " << e.to << ", " << e.cost << "}\n";
        }
        return out;
    }
};

struct Query {
    int v, val, qid;
    Query(int v, int val, int qid) : v(v), val(val), qid(qid) {}
};

void solve() {
    int n, q;
    cin >> n >> q;

    graph<int> g(n);
    vector<int> tpq(n + q), res(n + q);
    vector<vector<Query>> queries(n);
    for (int i = 0; i < n - 1 + q; ++i) {
        char ch;
        cin >> ch;
        if (ch == 'S') {
            int u, v;
            cin >> u >> v;
            --u, --v;
            g.link(u, v, i);
            tpq[i] = 0;
        }
        else if (ch == 'Q') {
            int u, v;
            cin >> u >> v;
            --u, --v;
            queries[v].emplace_back(u, i, i);
            tpq[i] = 1;
        }
        else {
            int u;
            cin >> u;
            --u;
            queries[u].emplace_back(-1, i, i);
            tpq[i] = 2;
        }
    }

    for (int i = 0; i < n; ++i) {
        reverse(all(g.adj[i]));
    }

    int tot_sz = 0;
    vector<bool> vis(n);
    vector<int> sz(n);

    auto get_sz = [&](auto self, int u, int _pid) -> void {
        sz[u] = 1;
        for (auto id : g.adj[u]) if (id != _pid and not vis[g(u, id)]) {
            int v = g(u, id);
            self(self, v, id);
            sz[u] += sz[v];
        }
    };

    auto find_cen = [&](auto self, int u, int _pid) -> int {
        for (auto id : g.adj[u]) if (id != _pid and not vis[g(u, id)]) {
            int v = g(u, id);
            if (sz[v] > (tot_sz >> 1)) {
                return self(self, v, id);
            }
        }
        return u;
    };

    auto get_cen = [&](int v) -> int {
        get_sz(get_sz, v, -1);
        tot_sz = sz[v];
        return find_cen(find_cen, v, -1);
    };

    auto fenw = make_fenwick_tree_sum<int>();
    fenw.build(n + q);

    vector<int> vis_dfs(n, n + q);
    vector<pair<int, int>> rst;
    auto dfs1 = [&](auto self, int u, int _pid, int pw) -> void {
        for (auto [v, val, qid] : queries[u]) {
            if (v == -1) {
                res[qid] += fenw.prefix(val);
            }
            else {
                res[qid] |= (vis_dfs[v] <= val);
            }
        }
        for (auto id : g.adj[u]) if (id != _pid and not vis[g(u, id)] and g.edge[id].cost < pw) {
            int v = g(u, id);
            self(self, v, id, g.edge[id].cost);
        }
    };

    auto add = [&](int u, int pw) -> void {
        vis_dfs[u] = pw;
        fenw.update(pw, 1);
        rst.emplace_back(u, pw);
    };

    auto dfs2 = [&](auto self, int u, int _pid, int pw) -> void {
        add(u, pw);
        for (auto id : g.adj[u]) if (id != _pid and not vis[g(u, id)] and g.edge[id].cost > pw) {
            int v = g(u, id);
            self(self, v, id, g.edge[id].cost);
        }
    };

    auto reset = [&]() -> void {
        while (not rst.empty()) {
            auto [u, pw] = rst.back();
            rst.pop_back();
            vis_dfs[u] = n + q;
            fenw.update(pw, -1);
        }
    };

    auto centroid = [&](auto self, int u) -> void {
        vis[u] = true;
        for (auto id : g.adj[u]) if (not vis[g(u, id)]) {
            int v = g(u, id);
            add(u, g.edge[id].cost);
            dfs1(dfs1, v, -1, g.edge[id].cost);
            {
                auto [u, pw] = rst.back();
                rst.pop_back();
                vis_dfs[u] = n + q;
                fenw.update(pw, -1);
            }
            dfs2(dfs2, v, -1, g.edge[id].cost);
        }
        add(u, 0);
        for (auto [v, val, qid] : queries[u]) {
            if (v == -1) {
                res[qid] += fenw.prefix(val);
            }
            else {
                res[qid] |= (vis_dfs[v] <= val);
            }
        }
        reset();

        for (auto id : g.adj[u]) if (not vis[g(u, id)]) {
            int v = g(u, id);
            int nxt_cen = get_cen(v);
            self(self, nxt_cen);
        }
    };

    int cen = get_cen(0);
    centroid(centroid, cen);

    for (int i = 0; i < n + q - 1; ++i) {
        if (tpq[i] == 1) {
            cout << (res[i] ? "yes" : "no") << "\n";
        }
        else if (tpq[i] == 2)   {
            cout << res[i] << "\n";
        }
    }
}

signed main() {

#ifndef CDuongg
    if (fopen(taskname".inp", "r"))
        assert(freopen(taskname".inp", "r", stdin)), assert(freopen(taskname".out", "w", stdout));
#else
    freopen("bai3.inp", "r", stdin);
    freopen("bai3.out", "w", stdout);
    auto start = chrono::high_resolution_clock::now();
#endif

    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1; //cin >> t;
    while(t--) solve();

#ifdef CDuongg
   // auto end = chrono::high_resolution_clock::now();
   // cout << "\n"; for(int i = 1; i <= 100; ++i) cout << '=';
   // cout << "\nExecution time: " << chrono::duration_cast<chrono::milliseconds> (end - start).count() << "[ms]" << endl;
#endif

}

Compilation message

servers.cpp:84:18: warning: use of 'auto' in parameter declaration only available with '-fconcepts-ts'
   84 |     int max_pref(auto pred) const{
      |                  ^~~~
servers.cpp: In constructor 'graph<T>::graph(const std::vector<std::vector<std::pair<int, T> > >&, bool)':
servers.cpp:153:51: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  153 |             for(auto u = 0; u < n; ++ u) for(auto [v, w]: adj[u]) if(u < v) link(u, v, w);
      |                                                   ^
servers.cpp:155:52: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  155 |         else for(auto u = 0; u < n; ++ u) for(auto [v, w]: adj[u]) orient(u, v, w);
      |                                                    ^
servers.cpp: In constructor 'graph<T>::graph(int, std::vector<std::array<int, 2> >&, bool)':
servers.cpp:159:18: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  159 |         for(auto [u, v]: edge) undirected ? link(u, v) : orient(u, v);
      |                  ^
servers.cpp: In constructor 'graph<T>::graph(int, std::vector<std::tuple<int, int, T> >&, bool)':
servers.cpp:163:18: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  163 |         for(auto [u, v, w]: edge) undirected ? link(u, v, w) : orient(u, v, w);
      |                  ^
servers.cpp: In member function 'void graph<T>::clear()':
servers.cpp:195:18: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  195 |         for(auto [u, v, w]: edge){
      |                  ^
servers.cpp: In lambda function:
servers.cpp:315:19: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  315 |         for (auto [v, val, qid] : queries[u]) {
      |                   ^
servers.cpp: In lambda function:
servers.cpp:345:18: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  345 |             auto [u, pw] = rst.back();
      |                  ^
servers.cpp: In lambda function:
servers.cpp:359:22: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  359 |                 auto [u, pw] = rst.back();
      |                      ^
servers.cpp:367:19: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  367 |         for (auto [v, val, qid] : queries[u]) {
      |                   ^
# 결과 실행 시간 메모리 Grader output
1 Correct 17 ms 5212 KB Output is correct
2 Correct 26 ms 6492 KB Output is correct
3 Correct 22 ms 6020 KB Output is correct
4 Correct 26 ms 6492 KB Output is correct
5 Correct 30 ms 6648 KB Output is correct
6 Correct 23 ms 6492 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 17 ms 5212 KB Output is correct
2 Correct 26 ms 6492 KB Output is correct
3 Correct 22 ms 6020 KB Output is correct
4 Correct 26 ms 6492 KB Output is correct
5 Correct 30 ms 6648 KB Output is correct
6 Correct 23 ms 6492 KB Output is correct
7 Correct 17 ms 5208 KB Output is correct
8 Incorrect 28 ms 5980 KB Extra information in the output file
9 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 5212 KB Output is correct
2 Correct 96 ms 23072 KB Output is correct
3 Correct 93 ms 23228 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 5212 KB Output is correct
2 Correct 96 ms 23072 KB Output is correct
3 Correct 93 ms 23228 KB Output is correct
4 Correct 16 ms 5212 KB Output is correct
5 Correct 92 ms 22912 KB Output is correct
6 Correct 63 ms 21040 KB Output is correct
7 Correct 66 ms 21252 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 5212 KB Output is correct
2 Correct 192 ms 27444 KB Output is correct
3 Correct 201 ms 27652 KB Output is correct
4 Correct 164 ms 28680 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 5212 KB Output is correct
2 Correct 192 ms 27444 KB Output is correct
3 Correct 201 ms 27652 KB Output is correct
4 Correct 164 ms 28680 KB Output is correct
5 Correct 17 ms 5016 KB Output is correct
6 Correct 222 ms 27140 KB Output is correct
7 Correct 182 ms 28564 KB Output is correct
8 Correct 204 ms 26884 KB Output is correct
9 Correct 202 ms 26628 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 5208 KB Output is correct
2 Correct 150 ms 22280 KB Output is correct
3 Correct 140 ms 21252 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 5208 KB Output is correct
2 Correct 150 ms 22280 KB Output is correct
3 Correct 140 ms 21252 KB Output is correct
4 Correct 17 ms 5264 KB Output is correct
5 Correct 155 ms 21844 KB Output is correct
6 Correct 147 ms 20880 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 5212 KB Output is correct
2 Correct 196 ms 27656 KB Output is correct
3 Correct 209 ms 27640 KB Output is correct
4 Correct 156 ms 28628 KB Output is correct
5 Correct 17 ms 5212 KB Output is correct
6 Correct 151 ms 21716 KB Output is correct
7 Correct 145 ms 20688 KB Output is correct
8 Correct 141 ms 21376 KB Output is correct
9 Correct 162 ms 21192 KB Output is correct
10 Correct 240 ms 24584 KB Output is correct
11 Correct 240 ms 24308 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 5212 KB Output is correct
2 Correct 196 ms 27656 KB Output is correct
3 Correct 209 ms 27640 KB Output is correct
4 Correct 156 ms 28628 KB Output is correct
5 Correct 17 ms 5212 KB Output is correct
6 Correct 151 ms 21716 KB Output is correct
7 Correct 145 ms 20688 KB Output is correct
8 Correct 141 ms 21376 KB Output is correct
9 Correct 162 ms 21192 KB Output is correct
10 Correct 240 ms 24584 KB Output is correct
11 Correct 240 ms 24308 KB Output is correct
12 Correct 18 ms 5208 KB Output is correct
13 Correct 217 ms 26728 KB Output is correct
14 Correct 182 ms 28080 KB Output is correct
15 Correct 198 ms 26372 KB Output is correct
16 Correct 218 ms 26376 KB Output is correct
17 Correct 17 ms 5248 KB Output is correct
18 Correct 160 ms 21512 KB Output is correct
19 Correct 168 ms 20488 KB Output is correct
20 Correct 153 ms 20996 KB Output is correct
21 Correct 166 ms 21104 KB Output is correct
22 Correct 264 ms 23816 KB Output is correct
23 Correct 265 ms 24324 KB Output is correct
24 Correct 247 ms 24836 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 19 ms 5408 KB Output is correct
2 Correct 25 ms 6484 KB Output is correct
3 Correct 22 ms 5968 KB Output is correct
4 Correct 25 ms 6484 KB Output is correct
5 Correct 25 ms 6748 KB Output is correct
6 Correct 23 ms 6492 KB Output is correct
7 Correct 16 ms 5468 KB Output is correct
8 Correct 88 ms 22912 KB Output is correct
9 Correct 86 ms 22912 KB Output is correct
10 Correct 16 ms 5208 KB Output is correct
11 Correct 184 ms 27144 KB Output is correct
12 Correct 184 ms 27140 KB Output is correct
13 Correct 167 ms 28228 KB Output is correct
14 Correct 18 ms 5208 KB Output is correct
15 Correct 158 ms 21768 KB Output is correct
16 Correct 145 ms 20684 KB Output is correct
17 Correct 154 ms 21256 KB Output is correct
18 Correct 143 ms 21180 KB Output is correct
19 Correct 249 ms 24648 KB Output is correct
20 Correct 242 ms 24324 KB Output is correct
21 Correct 101 ms 23332 KB Output is correct
22 Correct 108 ms 22516 KB Output is correct
23 Correct 130 ms 21572 KB Output is correct
24 Correct 143 ms 21512 KB Output is correct
25 Correct 217 ms 25192 KB Output is correct
26 Correct 157 ms 20744 KB Output is correct
27 Correct 147 ms 20860 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 19 ms 5408 KB Output is correct
2 Correct 25 ms 6484 KB Output is correct
3 Correct 22 ms 5968 KB Output is correct
4 Correct 25 ms 6484 KB Output is correct
5 Correct 25 ms 6748 KB Output is correct
6 Correct 23 ms 6492 KB Output is correct
7 Correct 16 ms 5468 KB Output is correct
8 Correct 88 ms 22912 KB Output is correct
9 Correct 86 ms 22912 KB Output is correct
10 Correct 16 ms 5208 KB Output is correct
11 Correct 184 ms 27144 KB Output is correct
12 Correct 184 ms 27140 KB Output is correct
13 Correct 167 ms 28228 KB Output is correct
14 Correct 18 ms 5208 KB Output is correct
15 Correct 158 ms 21768 KB Output is correct
16 Correct 145 ms 20684 KB Output is correct
17 Correct 154 ms 21256 KB Output is correct
18 Correct 143 ms 21180 KB Output is correct
19 Correct 249 ms 24648 KB Output is correct
20 Correct 242 ms 24324 KB Output is correct
21 Correct 101 ms 23332 KB Output is correct
22 Correct 108 ms 22516 KB Output is correct
23 Correct 130 ms 21572 KB Output is correct
24 Correct 143 ms 21512 KB Output is correct
25 Correct 217 ms 25192 KB Output is correct
26 Correct 157 ms 20744 KB Output is correct
27 Correct 147 ms 20860 KB Output is correct
28 Correct 33 ms 5052 KB Output is correct
29 Incorrect 46 ms 5964 KB Extra information in the output file
30 Halted 0 ms 0 KB -