Submission #698019

#TimeUsernameProblemLanguageResultExecution timeMemory
698019GusterGoose27Jail (JOI22_jail)C++17
100 / 100
893 ms101460 KiB
#include <bits/stdc++.h> using namespace std; typedef pair<int, int> pii; const int MAXN = 12e4; vector<int> edges[MAXN]; vector<int> edges_expanded[5*MAXN]; // nodes for queries, tree nodes (2light), tree nodes (4heavy) int in_deg[5*MAXN]; int N=0; int r=0; int n, m; int sz[MAXN]; int depth[MAXN]; int to_hld[MAXN]; int par[MAXN]; vector<int> in_hld[MAXN]; // bottom to top int light_ids[MAXN][2]; pii startend[MAXN]; void clear() { for (int i = 0; i < n; i++) { edges[i].clear(); to_hld[i] = -1; in_hld[i].clear(); startend[i] = pii(-1, -1); } for (int i = 0; i < N; i++) { edges_expanded[i].clear(); in_deg[i] = 0; } N=0; r=0; } void make_edge(int a, int b) { // assert(a != 17 || b != 18); in_deg[b]++; edges_expanded[a].push_back(b); } class stree { public: int lp, rp; stree *l = nullptr; stree *r = nullptr; int id; stree(int lv, int rv, bool ud) { // 1 => down, 0 => up lp = lv; rp = rv; id = N++; if (lp < rp) { int mid = (lp+rp)/2; l = new stree(lp, mid, ud); r = new stree(mid+1, rp, ud); if (ud) { make_edge(id, l->id); make_edge(id, r->id); } else { make_edge(l->id, id); make_edge(r->id, id); } } } void connect(int lv, int rv, int i, bool ud) { if (lp > rv || rp < lv) return; if (lp >= lv && rp <= rv) { if (ud) make_edge(i, id); else make_edge(id, i); return; } l->connect(lv, rv, i, ud); r->connect(lv, rv, i, ud); } }; stree *trees[MAXN][2]; void dfs(int cur = 0, int p = -1) { sz[cur] = 1; for (int nxt: edges[cur]) { if (nxt == p) continue; depth[nxt] = depth[cur]+1; par[nxt] = cur; dfs(nxt, cur); sz[cur] += sz[nxt]; } } void make_hld(int cur = 0, int p = -1) { for (int nxt: edges[cur]) { if (nxt == p) continue; if (sz[nxt] > sz[cur]/2) { if (to_hld[cur] == -1) { to_hld[cur] = cur; } to_hld[nxt] = to_hld[cur]; make_hld(nxt, cur); } else make_hld(nxt, cur); } if (to_hld[cur] != -1) in_hld[to_hld[cur]].push_back(cur); else { light_ids[cur][0] = N++; light_ids[cur][1] = N++; } } bool comp(int x, int y) { if (to_hld[x] == -1 && to_hld[y] == -1) return depth[x] < depth[y]; if (to_hld[x] == -1) { return pii(depth[x], depth[x]) < pii(depth[to_hld[y]], depth[y]); } if (to_hld[y] == -1) { return pii(depth[y], depth[y]) > pii(depth[to_hld[x]], depth[x]); } return pii(depth[to_hld[x]], depth[x]) < pii(depth[to_hld[y]], depth[y]); } void make_path(int x, int y, bool excx, bool excy) { if (x == y) { if (excx || excy) return; if (to_hld[x] == -1) { make_edge(light_ids[x][0], N-1); make_edge(N-1, light_ids[x][1]); return; } } if (comp(x, y)) { swap(x, y); swap(excx, excy); } if (to_hld[x] != -1 && to_hld[x] == to_hld[y]) { int curhld = to_hld[x]; int d1 = depth[in_hld[curhld][0]]-depth[x]; int d2 = depth[in_hld[curhld][0]]-depth[y]; if (excx) d1++; if (excy) d2--; trees[curhld][0]->connect(d1, d2, N-1, 0); trees[curhld][1]->connect(d1, d2, N-1, 1); return; } if (to_hld[x] == -1) { if (excx) { return make_path(par[x], y, 0, excy); } make_edge(light_ids[x][0], N-1); make_edge(N-1, light_ids[x][1]); return make_path(par[x], y, excx, excy); } int curhld = to_hld[x]; int d1 = depth[in_hld[curhld][0]]-depth[x]; int d2 = in_hld[curhld].size()-1; if (excx) { d1++; excx = 0; } trees[curhld][0]->connect(d1, d2, N-1, 0); trees[curhld][1]->connect(d1, d2, N-1, 1); return make_path(par[to_hld[x]], y, excx, excy); } void prune(int cur) { in_deg[cur] = -1; r++; // cout << cur << "\n"; for (int nxt: edges_expanded[cur]) { in_deg[nxt]--; if (in_deg[nxt] == 0) prune(nxt); } } int main() { int t; cin >> t; fill(to_hld, to_hld+MAXN, -1); fill(startend, startend+MAXN, pii(-1, -1)); while (t--) { cin >> n; for (int i = 0; i < n-1; i++) { int x, y; cin >> x >> y; x--; y--; edges[x].push_back(y); edges[y].push_back(x); } dfs(); make_hld(); for (int i = 0; i < n; i++) { if (to_hld[i] == i) { for (int j = 0; j < 2; j++) { trees[i][j] = new stree(0, in_hld[i].size()-1, j); } } } cin >> m; for (int i = 0; i < m; i++) { int x, y; cin >> x >> y; x--; y--; N++; startend[x].first = N-1; startend[y].second = N-1; if (to_hld[y] == -1) { make_edge(light_ids[y][1], N-1); } else { int curhld = to_hld[y]; int d = -depth[y]+depth[in_hld[curhld][0]]; trees[curhld][1]->connect(d, d, N-1, 0); } if (to_hld[x] == -1) { make_edge(N-1, light_ids[x][0]); } else { int curhld = to_hld[x]; int d = -depth[x]+depth[in_hld[curhld][0]]; trees[curhld][0]->connect(d, d, N-1, 1); } make_path(x, y, 1, 1); } for (int i = 0; i < n; i++) { if (startend[i].first != -1 && startend[i].second != -1) { make_edge(startend[i].first, startend[i].second); } } for (int i = 0; i < N; i++) { if (in_deg[i] == 0) prune(i); } if (r == N) { cout << "Yes\n"; } else cout << "No\n"; clear(); } }
#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...