제출 #1338578

#제출 시각아이디문제언어결과실행 시간메모리
1338578jajceslavInside information (BOI21_servers)C++20
100 / 100
647 ms149668 KiB
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

#define ll long long
#define ull unsigned long long
#define lll __int128_t
#define ulll __uint128_t
#define ld long double
#define lld __float128

#define fi first
#define se second
#define mp make_pair

#define fast ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)

template<typename T>
using V = vector<T>;
template<typename T>
using VV = V<V<T>>;
template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template<typename T>
using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

template<typename T, typename U>
bool chmax(T &x, U v) {return (v > x)? x=v,1 : 0;}
template<typename T, typename U>
bool chmin(T &x, U v) {return (v < x)? x=v,1 : 0;}

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rnd64(chrono::steady_clock::now().time_since_epoch().count());

// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")

// #define DEBUG

#ifdef DEBUG

#define _main "\e[36m"
#define _reset "\e[39m\n"

template<typename T>
inline void __print(T x) {cerr << x;}
template<typename T, typename U>
inline void __print(pair<T,U> x)
{
    cerr << "("; __print(x.fi); cerr << ", "; __print(x.se); cerr << ")";
}

inline void _print() {}
template<typename T, typename... U>
inline void _print(T x, U... y)
{
    __print(x);
    if(sizeof...(y)) cerr << ", ";
    _print(y...);
}

template<typename T>
inline void _print_arr(T x) {__print(x);}
template<typename T, typename... U>
inline void _print_arr(T x, int size, U... len)
{
    cerr << "[";
    bool has = sizeof...(len);
    for(int i = 0; i < size; i++)
    {
        if(i) cerr << "," << (has? "\n" : " ");
        _print_arr(x[i], len...);
    }
    cerr << "]";
}

#define _source source_location::current()
#define debug_pref(a) cerr << _main << _source.file_name() << ":" << _source.line() << ":" << _source.column() << " [" << a << "]";
#define debug(a...) {debug_pref(#a); cerr << " = ["; _print(a); cerr << "]" << _reset;}
#define debug_arr(a, sz...) {debug_pref(#a); cerr << " = "; _print_arr(a, sz); cerr << _reset;}

#endif
#ifndef DEBUG
#define debug(a...)
#define debug_arr(a, sz...)
#endif

/*

precalc order of appearence for each edge

lets look at C query

root tree at node c and look at all valid nodes, where we reach. a valid node will have all edges increasing on a path from c
for each node we store max edge
put all of them into ordered set to find number of nodes where max <= t

now how do we transition to children of c?

first go into child with maximum edge
recalculate set for subtree. check if path from v to p is valid to add p

now return to p
calculate values for subtree of v

now we go into v with second largest edge. this way we keep whatever we found for subtree
we do that and bla bla bla each nodes gets added O(logN) times in O(logN) complexity

for Q queries, do together with C, just keep another set of present nodes and that's it

*/

const int MAXN = 120005;

struct q_query
{
    int t;
    int v;
    int r;
    bool ans;
    q_query(int v, int r, int t): v(v), r(r), t(t), ans(0) {}
    q_query() {}
};

struct c_query
{
    int t;
    int v;
    int ans;
    c_query(int v, int t): v(v), t(t), ans(0) {}
    c_query() {}
};

namespace graph
{
    vector<pair<int, int> > g[MAXN];
    int sz[MAXN];
    bool used[MAXN];

    int ans[MAXN];
    q_query q1s[MAXN];
    c_query q2s[MAXN];
    vector<int> q1[MAXN];
    vector<int> q2[MAXN];
    bool q_tp[MAXN];

    ordered_set<int> vals[MAXN];
    map<int, int> nodes[MAXN];
    vector<int> pars[MAXN];

    void calc_sz(int v, int p)
    {
        sz[v] = 1;
        for(auto [e, c] : g[v])
        {
            if(used[c] || c == p)
                continue;
            calc_sz(c, v);
            sz[v] += sz[c];
        }
    }

    int find_centr(int v, int p, int cur_s)
    {
        for(auto [e, c] : g[v])
        {
            if(used[c] || c == p)
                continue;
            if(sz[c]*2 > cur_s)
                return find_centr(c, v, cur_s);
        }
        return v;
    }

    void add_to_set(int v, int p, int pp, int val)
    {
        debug("add", pp, v, val);
        nodes[pp][v] = val;
        vals[pp].insert(val);
        for(auto [e, c] : g[v])
        {
            if(e < val)
                continue;
            if(used[c] || c == p)
                continue;
            add_to_set(c, v, pp, e);
        }
    }

    void add_pars(int v, int p, int pp, int val)
    {
        pars[v].push_back(pp);
        for(auto [e, c] : g[v])
        {
            if(used[c] || c == p)
                continue;
            if(e > val)
                continue;
            add_pars(c, v, pp, e);
        }
    }
    

    void solve(int v, int p)
    {
        debug("solve()", v, p);
        calc_sz(v, -1);
        int cur_sz = sz[v];
        int c = find_centr(v, -1, cur_sz);

        debug("centr", c);
        used[c] = 1;
        add_pars(c, -1, c, 1e9);

        debug("add", c, c, -1);
        for(auto [e, u] : g[c])
        {
            if(used[u])
                continue;

            nodes[c][c] = e;
            vals[c].insert(e);

            solve(u, c);
            debug("back from child", c, u);

            nodes[c].erase(c);
            vals[c].erase(e);

            add_to_set(u, c, c, e);
        }

        nodes[c][c] = -1;
        vals[c].insert(-1);

        debug("answering queries", c);

        // debug("set: ", c);
        // cout << "SET " << c << '\n';
        // for(auto [v, val] : nodes[c])
        // {
        //     cout << v << ' ' << val << '\n';
        // }

        for(int pp : pars[c])
        {
            for(int q : q1[c])
            {
                int u = q1s[q].v;
                if(nodes[pp].count(u) == 0) {
                    continue;
                }
                int val = nodes[pp][u];
                q1s[q].ans |= val < q1s[q].t;
            }
            for(int q : q2[c])
            {
                int t = q2s[q].t;
                auto it = vals[pp].lower_bound(t);
                int res = 0;
                if(it == vals[pp].end())
                    res = vals[pp].size();
                else
                    res = vals[pp].order_of_key(*it);
                q2s[q].ans += res;
            }
        }

        used[c] = 0;
    }

    void add_edge(int a, int b, int t)
    {
        g[a].push_back(mp(t, b));
        g[b].push_back(mp(t, a));
    }

    void add_q_query(q_query &q, int i)
    {
        q1s[i] = q;
        q1[q.r].push_back(i);
        q_tp[i] = 0;
    }

    void add_c_query(c_query &q, int i)
    {
        q2s[i] = q;
        q2[q.v].push_back(i);
        q_tp[i] = 1;
    }

    void solve(int n)
    {
        for(int i = 0; i < n; i++)
        {
            sort(g[i].rbegin(), g[i].rend());
        }

        solve(0, -1);
    }

    void print_ans(int q)
    {
        for(int i = 0; i < q; i++)
        {
            if(q_tp[i])
            {
                cout << q2s[i].ans << '\n';
            }
            else
            {
                cout << (q1s[i].ans ? "yes" : "no") << '\n';
            }
        }
    }
}

int main()
{
    fast;
    int n, q; cin >> n >> q;

    vector<pair<int, int> > edg;
    int qs = 0;
    for(int i = 0; i < n+q-1; i++)
    {
        char c; cin >> c;
        if(c == 'S')
        {
            int a, b; cin >> a >> b; a--; b--;
            edg.push_back(mp(a, b));
        }
        else if(c == 'Q')
        {
            int r, v; cin >> v >> r; r--; v--;
            q_query qr(v, r, edg.size());
            graph::add_q_query(qr, qs++);
        }
        else
        {
            int v; cin >> v; v--;
            c_query qr(v, edg.size());
            graph::add_c_query(qr, qs++);
        }
    }

    for(int i = 0; i < n-1; i++)
    {
        int a = edg[i].fi, b = edg[i].se;
        graph::add_edge(a, b, i);
    }

    graph::solve(n);
    graph::print_ans(q);
}

/*

6 9
S 1 2
S 1 3
S 3 4
Q 5 1
S 4 5
S 1 6
Q 5 1
Q 1 5
C 1
C 2
C 3
C 4
C 5
C 6

6 6
S 1 5
S 1 4
S 1 3
S 1 2
S 1 6
C 1
C 2
C 3
C 4
C 5
C 6

*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...