제출 #675922

#제출 시각아이디문제언어결과실행 시간메모리
675922stanislavpolynInside information (BOI21_servers)C++17
100 / 100
1291 ms70832 KiB
#include <bits/stdc++.h>

#define fr(i, a, b) for (int i = (a); i <= (b); i++)
#define rf(i, a, b) for (int i = (a); i >= (b); i--)
#define fe(x, y) for (auto& x : y)

#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define mt make_tuple

#define pw(x) (1LL << (x))
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()

using namespace std;

mt19937_64 rng(chrono::system_clock::now().time_since_epoch().count());

#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
template <typename T>
using oset = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define fbo find_by_order
#define ook order_of_key

template <typename T>
bool umn(T& a, T b) {
    return a > b ? a = b, 1 : 0;
}
template <typename T>
bool umx(T& a, T b) {
    return a < b ? a = b, 1 : 0;
}

using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
template <typename T>
using ve = vector<T>;

const int N = 3e5 + 5;

#define dec abcd

int n, k;
ve<pii> g[N];
ve<int> dp[N];
ve<array<int, 3>> Q;

int timer;
int tin[N], tout[N];
int up[N][20];
int par[N], val[N];

bool inc[N][20];
bool dec[N][20];
int dep[N];

void dfs(int v = 1, int p = 0) {
    up[v][0] = p;
    fr (i, 1, 19) up[v][i] = up[up[v][i - 1]][i - 1];
    tin[v] = timer++;

    fe (to, g[v]) {
        if (to.fi == p) continue;
        par[to.fi] = v;
        val[to.fi] = to.se;
        dep[to.fi] = dep[v] + 1;
        dfs(to.fi, v);
    }

    tout[v] = timer++;
}

bool isUpper(int a, int b) {
    return tin[a] <= tin[b] && tout[a] >= tin[b];
}

int getLCA(int a, int b) {
    if (isUpper(a, b)) return a;
    if (isUpper(b, a)) return b;
    rf (i, 19, 0) {
        if (up[a][i] && !isUpper(up[a][i], b)) {
            a = up[a][i];
        }
    }
    return up[a][0];
}

int getDist(int a, int b) {
    return dep[a] + dep[b] - 2 * dep[getLCA(a, b)];
}

int goUp(int v, int d) {
    rf (i, 19, 0) {
        if (d - pw(i) >= 0) {
            v = up[v][i];
            d -= pw(i);
        }
    }
    assert(v);
    return v;
}

bool checkInc(int v, int d) {
    if (d == 0) return 1;
    int p = __lg(d);
    return inc[v][p] && inc[goUp(v, d - pw(p))][p];
}


bool checkDec(int v, int d) {
    if (d == 0) return 1;
    int p = __lg(d);
    return dec[v][p] && dec[goUp(v, d - pw(p))][p];
}

int getLastEdge(int a, int b) {
    assert(a != b);

    if (isUpper(a, b)) {
        return val[b];
    }
    if (isUpper(b, a)) {
        int v = goUp(a, dep[a] - dep[b] - 1);
        return val[v];
    }
    return val[b];
}

int checkPath(int a, int b) {
    if (a == b) return 1;

    if (isUpper(a, b)) {
        return checkDec(b, dep[b] - dep[a]);
    }
    if (isUpper(b, a)) {
        return checkInc(a, dep[a] - dep[b]);
    }
    int c = getLCA(a, b);

    int e1 = val[goUp(a, dep[a] - dep[c] - 1)];
    int e2 = val[goUp(b, dep[b] - dep[c] - 1)];
    if (e1 > e2) return 0;

    return checkInc(a, dep[a] - dep[c]) && checkDec(b, dep[b] - dep[c]);
}

ve<int> G[N];
int P[N];
int sz[N];
int cmpSz;
bool block[N];

void calcSz(int v, int p) {
    sz[v] = 1;
    fe (to, g[v]) {
        if (to.fi == p || block[to.fi]) continue;
        calcSz(to.fi, v);
        sz[v] += sz[to.fi];
    }
}

int findCentroid(int v, int p) {
    fe (to, g[v]) {
        if (to.fi == p || block[to.fi]) continue;
        if (sz[to.fi] > cmpSz / 2) {
            return findCentroid(to.fi, v);
        }
    }
    return v;
}

int go(int v = 1) {
    calcSz(v, 0);
    cmpSz = sz[v];
    int c = findCentroid(v, 0);
    block[c] = 1;
    fe (to, g[c]) {
        if (!block[to.fi]) {
            P[go(to.fi)] = c;
        }
    }
    return c;
}

int TIN[N], TOUT[N];

void dfs2(int v) {
    TIN[v] = timer++;
    fe (to, G[v]) {
        dfs2(to);
    }
    TOUT[v] = timer++;
}

bool inside(int v, int c) {
    return TIN[c] <= TIN[v] && TIN[v] <= TOUT[c];
}

ve<array<int, 3>> e;
int from[N];

ve<int> T[N];
int tot[N];

void upd(int pos, int x, ve<int>& t) {
    while (pos < sz(t)) {
        t[pos] += x;
        pos = pos | (pos + 1);
    }
}

int get(int pos, ve<int>& t) {
    int ans = 0;
    while (pos >= 0) {
        ans += t[pos];
        pos = (pos & (pos + 1)) - 1;
    }
    return ans;
}

void addEdge(int v) {
    int c = v;
    while (1) {
        if (inside(par[v], c)) {
            int a = v;
            int b = par[v];
            if (getDist(a, c) > getDist(b, c)) swap(a, b);

            if (checkPath(c, b)) {
                int e = getLastEdge(b, c);

                int p = lower_bound(all(g[c]), mp(-1, e), [](pii i, pii j) {
                    return i.se < j.se;
                }) - g[c].begin();
                assert(g[c][p].se == e);
                upd(p, 1, T[c]);
                tot[c]++;
                // dp[c][p]++;
            }
        }
        if (!P[c]) break;
        c = P[c];
    }
}

int getAns(int v, int t) {
    int c = v;
    int ans = 0;
    while (1) {
        if (checkPath(v, c)) {
            int e = (v == c ? -1 : getLastEdge(v, c));
            if (e <= t) {
                ans++;

                int p = upper_bound(all(g[c]), mp(-1, e), [](pii i, pii j) {
                    return i.se < j.se;
                }) - g[c].begin();

                ans += tot[c] - get(p - 1, T[c]);
                // rf (i, sz(g[c]) - 1, 0) {
                //     if (g[c][i].se > e) {
                //         ans += dp[c][i];
                //     } else {
                //         break;
                //     }
                // }
            }
        }

        if (!P[c]) break;
        c = P[c];
    }
    return ans;
}

int main() {
#ifndef LOCAL
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
#else
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
#endif

    cin >> n >> k;

    fr (i, 1, n + k - 1) {
        char c;
        cin >> c;
        if (c == 'S') {
            int a, b;
            cin >> a >> b;

            g[a].pb({b, i});
            g[b].pb({a, i});
            e.pb({i, a, b});
            // cout << a << " " << b << " " << i << "\n";
        }
        if (c == 'Q') {
            int a, d;
            cin >> a >> d;
            Q.pb({i, a, d});
        }
        if (c == 'C') {
            int x;
            cin >> x;
            Q.pb({i, x, -1});
        }
    }

    fr (i, 1, n) {
        // dp[i].resize(sz(g[i]));
        T[i].resize(sz(g[i]));
        sort(all(g[i]), [](pii a, pii b) {
            return a.se < b.se;
        });
    }

    dfs();

    fr (i, 1, n) {
        if (par[i]) {
            dec[i][0] = 1;
            inc[i][0] = 1;
        }
    }

    fr (p, 1, 19) {
        fr (i, 1, n) {
            if (up[i][p] && inc[i][p - 1] && inc[up[i][p - 1]][p - 1]) {
                if (val[goUp(i, pw(p - 1) - 1)] < val[up[i][p - 1]]) {
                    inc[i][p] = 1;
                }
            }

            if (up[i][p] && dec[i][p - 1] && dec[up[i][p - 1]][p - 1]) {
                if (val[goUp(i, pw(p - 1) - 1)] > val[up[i][p - 1]]) {
                    dec[i][p] = 1;
                }
            }
        }
    }

    int root = go();

    fr (i, 1, n) {
        if (P[i]) {
            G[P[i]].pb(i);
        }
    }
    timer = 0;
    dfs2(root);

    int ptr = 0;

    fe (cur, Q) {
        while (ptr < sz(e) && e[ptr][0] <= cur[0]) {
            if (isUpper(e[ptr][1], e[ptr][2])) swap(e[ptr][1], e[ptr][2]);
            addEdge(e[ptr][1]);
            ptr++;
        }

        if (cur[2] != -1) {
            if (cur[2] == cur[1]) {
                cout << "yes\n";
                continue;
            }

            if (checkPath(cur[2], cur[1]) && getLastEdge(cur[2], cur[1]) <= cur[0]) {
                cout << "yes\n";
            } else {
                cout << "no\n";
            }
        } else {
            cout << getAns(cur[1], cur[0]) << "\n";
        }
    }

    return 0;
}

/*
4 4
S 1 2
S 1 3
S 3 4
Q 2 1
Q 2 2
Q 2 3
Q 2 4
*/
#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...