Submission #1011282

#TimeUsernameProblemLanguageResultExecution timeMemory
1011282ForestedPrize (CEOI22_prize)C++17
35 / 100
2193 ms478844 KiB
#include <bits/stdc++.h> using namespace std; using i32 = int; using i64 = long long; template <typename T> using V = vector<T>; template <typename T> using VV = V<V<T>>; #define OVERRIDE4(a, b, c, d, ...) d #define REP2(i, n) for (i32 i = 0; i < (i32)(n); ++i) #define REP3(i, l, r) for (i32 i = (i32)(l); i < (i32)(r); ++i) #define REP(...) OVERRIDE4(__VA_ARGS__, REP3, REP2)(__VA_ARGS__) #define PER2(i, n) for (i32 i = (i32)(n)-1; i >= 0; --i) #define PER3(i, l, r) for (i32 i = (i32)(r)-1; i >= (i32)(l); --i) #define PER(...) OVERRIDE4(__VA_ARGS__, PER3, PER2)(__VA_ARGS__) #define LEN(x) (i32) size(x) #define ALL(x) begin(x), end(x) template <typename T> bool chmin(T &x, const T &y) { if (x > y) { x = y; return true; } return false; } template <typename T> bool chmax(T &x, const T &y) { if (x < y) { x = y; return true; } return false; } struct HLD { VV<i32> g; V<i32> par, sz, dep, head, in, out; void dfs0(i32 v) { if (!g[v].empty() && g[v].front() == par[v]) { swap(g[v].front(), g[v].back()); } for (i32 &u : g[v]) { if (u == par[v]) { continue; } par[u] = v; dep[u] = dep[v] + 1; dfs0(u); sz[v] += sz[u]; if (sz[u] > sz[g[v].front()]) { swap(g[v].front(), u); } } } void dfs1(i32 v, i32 &t) { in[v] = t++; for (i32 u : g[v]) { if (u == par[v]) { continue; } head[u] = (u == g[v].front() ? head[v] : u); dfs1(u, t); } out[v] = t; } HLD(const VV<i32> &g, i32 root) : g(g), par(LEN(g), -1), sz(LEN(g), 1), dep(LEN(g), 0), head(LEN(g), root), in(LEN(g), 0), out(LEN(g), 0) { dfs0(root); i32 t = 0; dfs1(root, t); } i32 lca(i32 u, i32 v) const { while (u != v) { if (in[u] > in[v]) { swap(u, v); } if (head[u] == head[v]) { break; } v = par[head[v]]; } return u; } }; class UnionFindWithPotential { V<i32> par; V<i32> diff; i32 root(i32 v) { if (par[v] < 0) { return v; } else { i32 p = par[v]; i32 r = root(par[v]); diff[v] += diff[p]; par[v] = r; return r; } } public: UnionFindWithPotential(i32 n) : par(n, -1), diff(n, 0) {} // a[u] - a[v] = x void unite(i32 u, i32 v, i32 x) { i32 ru = root(u), rv = root(v); if (ru == rv) { return; } if (-par[ru] > -par[rv]) { swap(ru, rv); swap(u, v); x = -x; } par[rv] += par[ru]; par[ru] = rv; diff[ru] = x - diff[u] + diff[v]; } // a[u] - a[v] i32 getd(i32 u, i32 v) { i32 r = root(u); i32 r2 = root(v); assert(r == r2); return diff[u] - diff[v]; } void show() { cout << '\n'; REP(i, LEN(par)) { i32 r = root(i); cout << r << ' ' << diff[i] << '\n'; } cout << '\n'; } }; int main() { i32 n, k, q, t; cin >> n >> k >> q >> t; V<i32> t0(n), t1(n); REP(i, n) { cin >> t0[i]; if (t0[i] > 0) { --t0[i]; } } REP(i, n) { cin >> t1[i]; if (t1[i] > 0) { --t1[i]; } } i32 r0 = (i32)(find(ALL(t0), -1) - t0.begin()); i32 r1 = (i32)(find(ALL(t1), -1) - t1.begin()); VV<i32> g0(n), g1(n); REP(i, n) { if (t0[i] != -1) { g0[t0[i]].push_back(i); } } REP(i, n) { if (t1[i] != -1) { g1[t1[i]].push_back(i); } } HLD hld0(g0, r0), hld1(g1, r1); V<i32> st(n); iota(ALL(st), 0); { mt19937 mt(998); shuffle(ALL(st), mt); } st.resize(k); V<i32> ord0 = st; V<i32> ord1 = st; sort(ALL(ord0), [&](i32 u, i32 v) -> bool { return hld0.in[u] < hld0.in[v]; }); sort(ALL(ord1), [&](i32 u, i32 v) -> bool { return hld1.in[u] < hld1.in[v]; }); V<pair<i32, i32>> qrys; if (q == k - 1) { REP(i, k - 1) { qrys.emplace_back(ord0[i], ord0[i + 1]); } } else { REP(i, k - 1) { qrys.emplace_back(ord0[i], ord0[i + 1]); } REP(i, k - 1) { qrys.emplace_back(ord1[i], ord1[i + 1]); } } REP(i, k) { cout << st[i] + 1 << " \n"[i + 1 == k]; } for (auto [a, b] : qrys) { cout << "? " << a + 1 << ' ' << b + 1 << '\n'; } cout << "!\n"; cout.flush(); using PCT = tuple<i32, i32, i32, i32>; V<PCT> resp(q); for (auto &[x, y, z, w] : resp) { cin >> x >> y >> z >> w; } V<pair<i32, i32>> dq(t); REP(i, t) { cin >> dq[i].first >> dq[i].second; --dq[i].first; --dq[i].second; } UnionFindWithPotential uf0(n), uf1(n); if (q == k - 1) { REP(i, k - 1) { auto [a, b] = qrys[i]; i32 lca0 = hld0.lca(a, b); i32 lca1 = hld1.lca(a, b); auto [x, y, z, w] = resp[i]; uf0.unite(a, lca0, x); uf0.unite(b, lca0, y); uf1.unite(a, lca1, z); uf1.unite(b, lca1, w); } } else { REP(i, k - 1) { auto [a, b] = qrys[i]; i32 lca0 = hld0.lca(a, b); auto [x, y, z, w] = resp[i]; uf0.unite(a, lca0, x); uf0.unite(b, lca0, y); } REP(i, k - 1) { auto [a, b] = qrys[k - 1 + i]; i32 lca1 = hld1.lca(a, b); auto [x, y, z, w] = resp[k - 1 + i]; uf1.unite(a, lca1, z); uf1.unite(b, lca1, w); //uf1.show(); } } V<pair<i32, i32>> dans(t); REP(i, t) { auto [a, b] = dq[i]; i32 lca0 = hld0.lca(a, b); i32 lca1 = hld1.lca(a, b); dans[i].first = uf0.getd(a, lca0) + uf0.getd(b, lca0); dans[i].second = uf1.getd(a, lca1) + uf1.getd(b, lca1); } REP(i, t) { cout << dans[i].first << ' ' << dans[i].second << '\n'; } cout.flush(); }
#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...