Submission #1196251

#TimeUsernameProblemLanguageResultExecution timeMemory
1196251anmattroiInside information (BOI21_servers)C++20
100 / 100
1084 ms114848 KiB
#include <bits/stdc++.h> #define maxn 120005 #define fi first #define se second using namespace std; using ii = pair<int, int>; const int INF = 1'000'000'000; int n, k; vector<ii> adj[maxn]; struct query { char type; int u, v; query() {} } queries[maxn+maxn]; int pe[maxn], d[maxn], f[17][maxn], g[17][maxn], nho[maxn], par[maxn], sz[maxn], tsz = 0, start[maxn], stop[maxn], id = 0; vector<int> lis[maxn]; int ASC[maxn], DESC[maxn]; int isAncestor(int u, int v) { return start[u] <= start[v] && stop[v] <= stop[u]; } int jump(int x, int k) { for (int i = 0; i < 17; i++) if (k>>i&1) x = f[i][x]; return x; } int LCA(int u, int v) { if (d[u] > d[v]) swap(u, v); if (d[u] < d[v]) v = jump(v, d[v]-d[u]); if (u == v) return u; for (int i = 16; i >= 0; i--) if (f[i][u] != f[i][v]) { u = f[i][u]; v = f[i][v]; } return f[0][u]; } void pfs(int u, int dad) { start[u] = ++id; f[0][u] = dad; g[0][u] = pe[u]; for (int i = 1; i < 17; i++) { f[i][u] = f[i-1][f[i-1][u]]; g[i][u] = max(g[i-1][u], g[i-1][f[i-1][u]]); } ASC[u] = (pe[u] < pe[dad] ? ASC[dad] : dad); DESC[u] = (pe[u] > pe[dad] ? DESC[dad] : dad); for (auto [v, l] : adj[u]) if (v != dad) { pe[v] = l; d[v] = d[u]+1; pfs(v, u); } stop[u] = id; } int ASCENSION(int u, int w) { return d[ASC[u]] <= d[w]; } int DECENSION(int u, int w) { return d[DESC[u]] <= d[w]; } int MAXIMUS(int u, int v, int w, int TIME) { int k, ans = 0; k = d[u]-d[w]; for (int i = 0; i < 17; i++) if (k>>i&1) { ans = max(ans, g[i][u]); u = f[i][u]; } k = d[v]-d[w]; for (int i = 0; i < 17; i++) if (k>>i&1) { ans = max(ans, g[i][v]); v = f[i][v]; } return ans < TIME; } int possiblePath(int u, int v, int TIME) { int w = LCA(u, v); int condition = 1; condition &= ASCENSION(u, w); condition &= DECENSION(v, w); if (w != u && w != v) condition &= (pe[jump(u, d[u]-d[w]-1)] < pe[jump(v, d[v]-d[w]-1)]); condition &= MAXIMUS(u, v, w, TIME); return condition; } int lastEdge(int u, int v) { if (isAncestor(v, u)) return pe[jump(u, d[u]-d[v]-1)]; return pe[v]; } int firstEdge(int u, int v) { if (isAncestor(u, v)) return pe[jump(v, d[v]-d[u]-1)]; return pe[u]; } void queryQ(int u, int v, int TIME) { cout << (possiblePath(u, v, TIME) ? "yes\n" : "no\n"); } void resz(int u, int dad) { ++tsz; sz[u] = 1; for (auto [v, l] : adj[u]) if (!nho[v] && v != dad) { resz(v, u); sz[u] += sz[v]; } } int findCentroid(int u, int dad) { for (auto [v, l] : adj[u]) if (v != dad && !nho[v] && sz[v] > tsz/2) return findCentroid(v, u); return u; } void dcp(int u, int r) { tsz = 0; resz(u, 0); int C = findCentroid(u, 0); nho[C] = 1; par[C] = r; for (auto [v, l] : adj[C]) if (!nho[v]) dcp(v, C); } struct node { int val = 0; node *leftChild = nullptr, *rightChild = nullptr; node() {} node(int _val) : val(_val) {} void extendLeft() { if (leftChild == nullptr) leftChild = new node; } void extendRight() { if (rightChild == nullptr) rightChild = new node; } }; node *st[maxn]; void upd(int u, int d, node *cur, int lo = 1, int hi = n+k-1) { if (lo == hi) { cur->val += d; return; } int mid = (lo + hi) >> 1; if (u <= mid) { cur->extendLeft(); upd(u, d, cur->leftChild, lo, mid); } else { cur->extendRight(); upd(u, d, cur->rightChild, mid+1, hi); } cur->val = (cur->leftChild == nullptr ? 0 : cur->leftChild->val) + (cur->rightChild == nullptr ? 0 : cur->rightChild->val); } int get(int u, int v, node *cur, int lo = 1, int hi = n+k-1) { if (u <= lo && hi <= v) return cur->val; int mid = (lo + hi) >> 1; return ((u <= mid && cur->leftChild != nullptr) ? get(u, v, cur->leftChild, lo, mid) : 0) + ((v > mid && cur->rightChild != nullptr) ? get(u, v, cur->rightChild, mid+1, hi) : 0); } int ID = 0; struct pizza { int x, y, z; pizza() {} pizza(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {} bool operator < (const pizza &other) const { return y < other.y; } } skibidi[17*maxn]; void init() { for (int i = 1; i <= n; i++) st[i] = new node(0); for (int i = 1; i <= n; i++) { int j = par[i]; while (j) { if (!possiblePath(j, i, INT_MAX)) { j = par[j]; continue; } skibidi[++ID] = pizza(j, lastEdge(j, i), firstEdge(j, i)); j = par[j]; } } sort(skibidi + 1, skibidi + ID + 1); } void queryC(int x, int TIME) { int ans = st[x]->val+1; for (int y = x; y = par[y];) { if (!possiblePath(x, y, TIME)) continue; ++ans; int xd = lastEdge(x, y); if (xd < n+k-1) ans += get(xd+1, n+k-1, st[y]); } cout << ans << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(NULL); cin >> n >> k; for (int i = 1; i < n+k; i++) { cin >> queries[i].type >> queries[i].u; if (queries[i].type != 'C') cin >> queries[i].v; if (queries[i].type == 'S') { adj[queries[i].u].emplace_back(queries[i].v, i); adj[queries[i].v].emplace_back(queries[i].u, i); } } pfs(1, 0); dcp(1, 0); init(); for (int i = 1, it = 1; i < n+k; i++) { while (it <= ID && skibidi[it].y < i) { auto [x, y, z] = skibidi[it]; upd(z, 1, st[x]); ++it; } if (queries[i].type == 'Q') queryQ(queries[i].v, queries[i].u, i); else if (queries[i].type == 'C') queryC(queries[i].u, i); } }
#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...