diff --git a/algorithms/graph/lca.cpp b/algorithms/graph/lca.cpp index 151af9df76b4fdc9f2666eabf6a2781aa2163ac8..a0efdf7c396c2218e7ca56ce806176a38bfe6a13 100644 --- a/algorithms/graph/lca.cpp +++ b/algorithms/graph/lca.cpp @@ -60,40 +60,40 @@ struct LCA { dfs(u.fi, v, u.se); } - int query(int p, int q) { + int query(int a, int b) { int ans = 0; - if (h[p] < h[q]) - swap(p, q); + if (h[a] < h[b]) + swap(a, b); for (int i = MAXLOG - 1; i >= 0; --i) - if (par[p][i] != -1 && h[par[p][i]] >= h[q]) { - ans = op(ans, cost[p][i]); - p = par[p][i]; + if (par[a][i] != -1 && h[par[a][i]] >= h[b]) { + ans = op(ans, cost[a][i]); + a = par[a][i]; } - if (p == q) { + if (a == b) { #ifdef COST return ans; #else - return p; + return a; #endif } for (int i = MAXLOG - 1; i >= 0; --i) - if (par[p][i] != -1 && par[p][i] != par[q][i]) { - ans = op(ans, op(cost[p][i], cost[q][i])); - p = par[p][i]; - q = par[q][i]; + if (par[a][i] != -1 && par[a][i] != par[b][i]) { + ans = op(ans, op(cost[a][i], cost[b][i])); + a = par[a][i]; + b = par[b][i]; } #ifdef COST - if (p == q) + if (a == b) return ans; else - return op(ans, op(cost[p][0], cost[q][0])); + return op(ans, op(cost[a][0], cost[b][0])); #else - return par[p][0]; + return par[a][0]; #endif } }; diff --git a/algorithms/graph/steiner_tree.cpp b/algorithms/graph/steiner_tree.cpp index 8dcd3d011029c3dfe220b177f5f3e3b12d917ce2..829ac259083f0ad338e4259549691147fa84c7fe 100644 --- a/algorithms/graph/steiner_tree.cpp +++ b/algorithms/graph/steiner_tree.cpp @@ -8,7 +8,7 @@ /// The algorithm works by using dynamic programming, where dp[i][mask] /// stores the value of a Steiner tree rooted at $i$ containing the terminal /// nodes represented by the bits in bitmask. The algorithm iterates over all -/// bitmasks, and at each iteration $mask$ every pair of complementary subsets +/// bitmasks, and, at each iteration $mask$, every pair of complementary subsets /// are tested and dp[i][mask] is updated with the value given by the /// combination of both trees. Then, still at step $mask$, dp[j][mask] is /// updated for every $j$ with the ``extension'' of $i$ (for every $i$), as if @@ -28,13 +28,13 @@ int dp[MAXN][1 << MAXT]; int steiner_tree(int n, int t) { floyd_warshall(n); - fill(dp[0], dp[0] + MAXN * (1 << MAXT), inf); + mset(dp, inf); for (int i = 0; i < t; ++i) dp[i][1 << i] = 0; for (int mask = 1; mask < (1 << t); ++mask) { for (int i = 0; i < n; ++i) - for (int ss = mask; ss > 0; smask = (ss - 1) & mask) + for (int ss = mask; ss > 0; ss = (ss - 1) & mask) dp[i][mask] = min(dp[i][mask], dp[i][ss] + dp[i][mask ^ ss]); diff --git a/contests/SBC18/B.cpp b/contests/SBC18/B.cpp index 0931aac673235e5c23807b142565c9b7d7ec871f..d08d5c40e291257b3fb3f9bcc30d4e5d8eeb1bae 100644 --- a/contests/SBC18/B.cpp +++ b/contests/SBC18/B.cpp @@ -1,6 +1,5 @@ #include <bits/stdc++.h> -#define MAX 101 #define EPS 1e-6 #define MOD 1000000007 #define inf 0x3f3f3f3f @@ -21,53 +20,48 @@ using ll = long long; using ii = pair<int,int>; int foi[500]; -int mat[MAX][MAX]; -int dp[MAX][MAX]; +int dp[102][102]; int main() { ios::sync_with_stdio(0); cin.tie(0); - for (int i = 0; i < MAX; ++i) { - dp[i][0] = 499; - dp[0][i] = 499; + int N = 100; + for (int i = 0; i < N; ++i) { dp[i][i] = 499; + dp[0][i] = 499; + dp[i][0] = 499; } - for (int i = 1; i < MAX; ++i) { - for (int j = 1; j < MAX; ++j) { + for (int i = 1; i <= N; ++i) { + for (int j = 1; j <= N; ++j) { if (i != j) { mset(foi, 0); for (int k = 1; k <= i; ++k) foi[dp[i-k][j]] = 1; for (int k = 1; k <= j; ++k) foi[dp[i][j-k]] = 1; - - int mm = min(i, j); - for (int k = 1; k <= mm; ++k) + for (int k = 1; k <= min(i, j); ++k) foi[dp[i-k][j-k]] = 1; - int res = -1; - for (int k = 0; k < 500; ++k) + for (int k = 0; k <= 500; ++k) if (!foi[k]) { - res = k; + dp[i][j] = k; break; } - - dp[i][j] = res; } } } - - int ans = 0; + int n; cin >> n; + int ans = 0; for (int i = 0; i < n; ++i) { - int a, b; cin >> a >> b; - if (dp[a][b] == 499) + int a, b; cin >> a >> b; + if (a == b) return cout << 'Y' << ende, 0; ans ^= dp[a][b]; } - cout << ((ans) ? 'Y' : 'N') << ende; + cout << (ans ? 'Y' : 'N') << ende; return 0; } diff --git a/contests/SBC18/C.cpp b/contests/SBC18/C.cpp index 7b79559b04afff8d1d2b8300d905e6212d2946ac..818af61c570f56f401c12dd02b3342d695a75b5d 100644 --- a/contests/SBC18/C.cpp +++ b/contests/SBC18/C.cpp @@ -1,14 +1,13 @@ #include <bits/stdc++.h> #define MAX 101010 -#define MOD 1000000007 #define EPS 1e-6 +#define MOD 1000000007 #define inf 0x3f3f3f3f #define llinf 0x3f3f3f3f3f3f3f3f #define fi first #define se second -#define sz size() #define pb push_back #define ende '\n' @@ -18,74 +17,65 @@ using namespace std; -typedef long long ll; -typedef pair<ll,ll> ii; +using ll = long long; +using ii = pair<int,int>; -ll tree[MAX]; +int tree[MAX]; -ll query(int idx) { - ll sum = 0; - for (; idx > 0; idx -= (idx & -idx)) +int query(int idx) { + int sum = 0; + for ( ; idx > 0; idx -= (idx & -idx)) sum += tree[idx]; - return sum; } - -void update(int idx, ll val) { - for (; idx <= MAX; idx += (idx & -idx)) +void update(int idx, int val) { + for ( ; idx < MAX; idx += (idx & -idx)) tree[idx] += val; } - int main() { ios::sync_with_stdio(0); cin.tie(0); - ll x, y; cin >> x >> y; - ll h, v; cin >> h >> v; - - ll a, b; - vector<ii> H, V; - vector<ll> h1, v1; - vector<ll> hh, vv; - map<ll,ll> Mh, Mv; + int x, y; cin >> x >> y; + int h, v; cin >> h >> v; + vector<ii> H(h), V(v); - for (ll i = 0; i < h; ++i) { - cin >> a >> b; - H.pb(ii(b, a)); - h1.pb(a); + for (int i = 0; i < h; ++i) { + int x1, x2; cin >> x1 >> x2; + H[i] = ii(x1, x2); } - for (ll i = 0; i < v; ++i) { - cin >> a >> b; - V.pb(ii(b, a)); - v1.pb(a); + for (int i = 0; i < v; ++i) { + int y1, y2; cin >> y1 >> y2; + V[i] = ii(y1, y2); } sort(all(H)); - sort(all(V)); - sort(all(v1)); - sort(all(h1)); - - for (int i = 0; i < h; ++i) Mh[h1[i]] = i + 1; - for (int i = 0; i < v; ++i) Mv[v1[i]] = i + 1; - - for (auto i : H) hh.pb(Mh[i.se]); - for (auto i : V) vv.pb(Mv[i.se]); + for (int i = 0; i < h; ++i) + H[i].fi = i + 1; + sort(all(H), [](ii a, ii b) { + return a.se < b.se; + }); - ll ans = (h + 1) * (v + 1); + sort(all(V)); + for (int i = 0; i < v; ++i) + V[i].fi = i + 1; + sort(all(V), [](ii a, ii b) { + return a.se < b.se; + }); - mset(tree, 0); + ll ans = (h + 1LL) * (v + 1LL); for (int i = h - 1; i >= 0; --i) { - ans += query(hh[i]); - update(hh[i], 1); + ans += query(H[i].fi); + update(H[i].fi, 1); } - + mset(tree, 0); for (int i = v - 1; i >= 0; --i) { - ans += query(vv[i]); - update(vv[i], 1); + ans += query(V[i].fi); + update(V[i].fi, 1); } cout << ans << ende; diff --git a/contests/SBC18/D.cpp b/contests/SBC18/D.cpp index d3ec046fa9dc0209e1482b9a05e4c3a89d3d31bf..ebfbb3e8b597d8d171e89ef14573fb85815c2fcf 100644 --- a/contests/SBC18/D.cpp +++ b/contests/SBC18/D.cpp @@ -1,14 +1,12 @@ #include <bits/stdc++.h> -#define MAX 0 -#define MOD 1000000007 #define EPS 1e-6 +#define MOD 1000000007 #define inf 0x3f3f3f3f #define llinf 0x3f3f3f3f3f3f3f3f #define fi first #define se second -#define sz size() #define pb push_back #define ende '\n' @@ -18,21 +16,20 @@ using namespace std; -typedef long long ll; -typedef pair<int,int> ii; +using ll = long long; +using ii = pair<int,int>; int main() { ios::sync_with_stdio(0); cin.tie(0); - int ans = 0; int n; cin >> n; + int ans = 0; for (int i = 0; i < n; ++i) { int x; cin >> x; - if (x != 1) ans++; + ans += (x != 1); } cout << ans << ende; - return 0; } diff --git a/contests/SBC18/E.cpp b/contests/SBC18/E.cpp index caf757e9178d9d87c85ba2e9a2a1b9aba5a6c0ec..8e3600cca06ea3354f3c9df4e9e2f6d24a818dfe 100644 --- a/contests/SBC18/E.cpp +++ b/contests/SBC18/E.cpp @@ -1,14 +1,12 @@ #include <bits/stdc++.h> -#define MAX 0 -#define MOD 1000000007 #define EPS 1e-6 +#define MOD 1000000007 #define inf 0x3f3f3f3f #define llinf 0x3f3f3f3f3f3f3f3f #define fi first #define se second -#define sz size() #define pb push_back #define ende '\n' @@ -18,25 +16,25 @@ using namespace std; -typedef long long ll; -typedef pair<int,int> ii; +using ll = long long; +using ii = pair<int,int>; int main() { ios::sync_with_stdio(0); cin.tie(0); - string a, b; - cin >> a >> b; - - int na = a.sz, nb = b.sz; - int ans = na - nb + 1; - for (int i = 0; i <= na - nb; ++i) { - for (int j = 0; j < nb; ++j) { - if (b[j] == a[i+j]) { - ans--; + string s, t; cin >> s >> t; + int ans = 0; + for (int i = 0; i <= s.size() - t.size(); ++i) { + bool poss = true; + for (int j = 0; j < t.size(); ++j) + if (s[i+j] == t[j]) { + poss = false; break; } - } + + if (poss) + ans++; } cout << ans << ende; diff --git a/contests/SBC18/F.cpp b/contests/SBC18/F.cpp index d91a9daa896d432bf3ff3dc716515de731c06381..294882d1e8bfb6ff89cb6e3713419a02095b942b 100644 --- a/contests/SBC18/F.cpp +++ b/contests/SBC18/F.cpp @@ -1,14 +1,12 @@ #include <bits/stdc++.h> -#define MAX 0 -#define MOD 1000000007 #define EPS 1e-6 +#define MOD 1000000007 #define inf 0x3f3f3f3f #define llinf 0x3f3f3f3f3f3f3f3f #define fi first #define se second -#define sz size() #define pb push_back #define ende '\n' @@ -18,59 +16,61 @@ using namespace std; -typedef long long ll; -typedef pair<int,int> ii; +using ll = long long; +using ii = pair<int,int>; -typedef struct elem { - int i, f, o, p; - elem(int i, int f, int o, int p) : i(i), f(f), o(o), p(p) {} -} elem; +struct Show { int i, f, o, s, nxt; }; -int n; -vector<elem> v; -int prox[1010]; -int dp[1010][1300]; +int N, S; +vector<Show> v; +int dp[1010][3010]; -int solve(int i, int bit) { - if (i == -1 or i == v.sz) { - if (bit == (1 << n) - 1) return 0; - else return -inf; +int solve(int i, int mask) { + if (i == N) { + if (mask == (1 << S) - 1) + return 0; + return -inf; } - if (dp[i][bit] != -1) - return dp[i][bit]; - - return dp[i][bit] = max(solve(prox[i], bit | (1 << v[i].p)) + v[i].o, solve(i + 1, bit)); + if (dp[i][mask] != -1) + return dp[i][mask]; + + int op1 = solve(v[i].nxt, mask | (1 << v[i].s)) + v[i].o; + int op2 = solve(i + 1, mask); + return dp[i][mask] = max(op1, op2); } - int main() { ios::sync_with_stdio(0); cin.tie(0); - mset(dp, -1); - mset(prox, -1); - cin >> n; + int n; cin >> n; + S = n; for (int i = 0; i < n; ++i) { int m; cin >> m; for (int j = 0; j < m; ++j) { - int a, b, c; cin >> a >> b >> c; - v.pb(elem(a, b, c, i)); + int ii, ff, oo; cin >> ii >> ff >> oo; + v.pb({ii, ff, oo, i, -1}); } } - sort(all(v), [](elem a, elem b) { - return a.i < b.i; + sort(all(v), [](Show a, Show b) { + return a.i < b.i; }); - for (int i = 0; i < v.sz; ++i) - for (int j = i + 1; j < v.sz; ++j) + N = v.size(); + for (int i = 0; i < N; ++i) { + for (int j = i + 1; j < N; ++j) if (v[j].i >= v[i].f) { - prox[i] = j; + v[i].nxt = j; break; } - int ans = solve(0, 0); - cout << ((ans < 0) ? -1 : ans) << ende; + if (v[i].nxt == -1) + v[i].nxt = N; + } + + mset(dp, -1); + cout << max(-1, solve(0, 0)) << ende; return 0; } diff --git a/contests/SBC18/G.cpp b/contests/SBC18/G.cpp index 736aa3970ae7b5300174aea139139fd356b03f02..a96f5ceba6d8d1212d905c282cf2cc73bb7cdeba 100644 --- a/contests/SBC18/G.cpp +++ b/contests/SBC18/G.cpp @@ -1,6 +1,5 @@ #include <bits/stdc++.h> -#define MAX 3010 #define EPS 1e-6 #define MOD 1000000007 #define inf 0x3f3f3f3f @@ -17,139 +16,120 @@ using namespace std; -typedef long long ll; -typedef pair<int,int> ii; +using ll = long long; +using ii = pair<int,int>; +using iii = pair<ii,int>; -struct edge { - int u; - int flow, cap; - int rev; - - edge(int u, int flow, int cap, int rev) : - u(u), flow(flow), cap(cap), rev(rev) - {} -}; - - -int depth[MAX]; -int start[MAX]; -vector<edge> graph[MAX]; +struct Dinic { + struct Edge { int u, f, c, r; }; + int N; + vector<int> depth, start; + vector<vector<Edge>> graph; -void add_edge(int s, int t, int c) { - edge forward(t, 0, c, graph[t].size()); - edge backward(s, 0, 0, graph[s].size()); + Dinic(int N) : + N(N), depth(N), start(N), graph(N) {} - graph[s].pb(forward); - graph[t].pb(backward); -} + void add_edge(int u, int v, int c) { + Edge forw = { v, 0, c, (int) graph[v].size() }; + Edge back = { u, 0, 0, (int) graph[u].size() }; + graph[u].pb(forw); + graph[v].pb(back); + } + bool bfs(int s, int t) { + queue<int> Q; + Q.push(s); -bool bfs(int s, int t) { - queue<int> Q; - Q.push(s); + fill(all(depth), -1); + depth[s] = 0; - mset(depth, -1); - depth[s] = 0; + while (!Q.empty()) { + int v = Q.front(); Q.pop(); - while (!Q.empty()) { - int v = Q.front(); Q.pop(); - - for (auto i : graph[v]) { - if (depth[i.u] == -1 && i.flow < i.cap) { - depth[i.u] = depth[v] + 1; - Q.push(i.u); - } + for (auto i : graph[v]) + if (depth[i.u] == -1 && i.f < i.c) { + depth[i.u] = depth[v] + 1; + Q.push(i.u); + } } - } - - return depth[t] != -1; -} + return depth[t] != -1; + } -int dfs(int s, int t, int flow) { - if (s == t) - return flow; + int dfs(int s, int t, int f) { + if (s == t) return f; - for ( ; start[s] < graph[s].size(); ++start[s]) { - edge &e = graph[s][start[s]]; + for ( ; start[s] < graph[s].size(); ++start[s]) { + Edge &e = graph[s][start[s]]; - if (depth[e.u] == depth[s] + 1 && e.flow < e.cap) { - int min_flow = dfs(e.u, t, min(flow, e.cap - e.flow)); + if (depth[e.u] == depth[s] + 1 && e.f < e.c) { + int min_f = dfs(e.u, t, min(f, e.c - e.f)); - if (min_flow > 0) { - e.flow += min_flow; - graph[e.u][e.rev].flow -= min_flow; - return min_flow; + if (min_f > 0) { + e.f += min_f; + graph[e.u][e.r].f -= min_f; + return min_f; + } } } - } - - return 0; -} - - -int dinic(int s, int t) { - int ans = 0; - - while (bfs(s, t)) { - mset(start, 0); - while (int flow = dfs(s, t, inf)) - ans += flow; + return 0; } - return ans; -} - + int run(int s, int t) { + int ans = 0; + while (bfs(s, t)) { + fill(all(start), 0); + while (int flow = dfs(s, t, inf)) + ans += flow; + } + return ans; + } +}; int main() { ios::sync_with_stdio(0); cin.tie(0); int p, r, c; cin >> p >> r >> c; - int s = 0, t = MAX - 1; - int dem = 0; + vector<int> vp(p); + vector<int> vr(r); - vector<int> dems(p); - for (auto &i : dems) { + int sum = 0; + for (auto &i : vp) { cin >> i; - dem += i; + sum += i; } - vector<int> ests(r); - for (auto &i : ests) cin >> i; + for (auto &i : vr) cin >> i; - vector<pair<ii,int>> total; + vector<iii> v(c); for (int i = 0; i < c; ++i) { - int a, b, T; cin >> a >> b >> T; - total.pb(make_pair(ii(a, b), T)); + int a, b, x; cin >> a >> b >> x; + v[i] = {{a, b}, x}; } - - int L = 0, R = 1010101; - for (int i = 0; i < 20; ++i) { + int L = 0, R = 1001000; + for (int i = 0; i < 30; ++i) { int m = (L + R) / 2; - for (int j = 0; j < p; ++j) - add_edge(j + 1 + r, t, dems[j]); - + Dinic dinic(r + p + 5); for (int j = 0; j < r; ++j) - add_edge(s, j + 1, ests[j]); - - for (auto j : total) - if (j.se <= m) - add_edge(j.fi.se, j.fi.fi + r, inf); + dinic.add_edge(0, j + 1, vr[j]); + for (int j = 0; j < p; ++j) + dinic.add_edge(j + 1 + r, r + p + 4, vp[j]); - if (dinic(s, t) < dem) - L = m + 1; - else - R = m - 1; + for (int j = 0; j < c; ++j) + if (v[j].se <= m) + dinic.add_edge(v[j].fi.se, v[j].fi.fi + r, inf); - for (int j = 0; j < MAX; ++j) - graph[j].clear(); + if (dinic.run(0, r + p + 4) < sum) + L = m; + else + R= m; } - cout << (L >= 1010101 ? -1 : L) << ende; + cout << ((R > 1000100) ? -1 : R) << ende; return 0; } diff --git a/contests/SBC18/I.cpp b/contests/SBC18/I.cpp index c44abef09c104a5fcb400c3569f0b589f559992a..637a876b682e7871347b4afbaa95a6026ee85b23 100644 --- a/contests/SBC18/I.cpp +++ b/contests/SBC18/I.cpp @@ -1,14 +1,12 @@ #include <bits/stdc++.h> -#define MAX 0 -#define MOD 1000000007 #define EPS 1e-6 +#define MOD 1000000007 #define inf 0x3f3f3f3f #define llinf 0x3f3f3f3f3f3f3f3f #define fi first #define se second -#define sz size() #define pb push_back #define ende '\n' @@ -18,44 +16,45 @@ using namespace std; -typedef long long ll; -typedef pair<int,int> ii; - -bool v[1010]; -vector<int> u[1010]; +using ll = long long; +using ii = pair<int,int>; int main() { ios::sync_with_stdio(0); cin.tie(0); - int x, y; int n, m; cin >> n >> m; int l; cin >> l; + int acc = 0; + + vector<int> lamp(m); for (int i = 0; i < l; ++i) { - cin >> x; - v[x] = true; + int x; cin >> x; x--; + lamp[x] = 1; + acc++; } + vector<vector<int>> inte(n); for (int i = 0; i < n; ++i) { - cin >> x; - for (int j = 0; j < x; ++j) { - cin >> y; - u[i].pb(y); + int k; cin >> k; + for (int j = 0; j < k; ++j) { + int x; cin >> x; x--; + inte[i].pb(x); } } + if (acc == 0) + return cout << 0 << ende, 0; + int ans = 0; for (int i = 0; i < 2; ++i) { for (int j = 0; j < n; ++j) { - for (auto k : u[j]) - v[k] = !v[k]; - ans++; - bool done = true; - for (int k = 1; k <= m; ++k) - done &= !v[k]; + for (auto k : inte[j]) + if (lamp[k]) { acc--; lamp[k] = 0; } + else { acc++; lamp[k] = 1; } - if (done) + if (acc == 0) return cout << ans << ende, 0; } } diff --git a/contests/SBC18/J.cpp b/contests/SBC18/J.cpp index 9401290795e10f308d23125f3a93bef54cd9c8ce..8aa4ea5415d63aa518f6b17e8cea70074a3cad5d 100644 --- a/contests/SBC18/J.cpp +++ b/contests/SBC18/J.cpp @@ -1,5 +1,7 @@ #include <bits/stdc++.h> +#define MAX 105 +#define MAXT 11 #define EPS 1e-6 #define MOD 1000000007 #define inf 0x3f3f3f3f @@ -18,9 +20,10 @@ using namespace std; using ll = long long; using ii = pair<int,int>; +using dd = pair<double,double>; -double graph[101][101]; -double dp[101][2100]; +double dist[MAX][MAX]; +double dp[MAX][1 << MAXT]; int main() { ios::sync_with_stdio(0); @@ -28,30 +31,30 @@ int main() { cout << setprecision(5) << fixed; int n, k; cin >> n >> k; - vector<double> x(n), y(n); + vector<dd> v(n); for (int i = 0; i < n; ++i) - cin >> x[i] >> y[i]; + cin >> v[i].fi >> v[i].se; for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) - graph[i][j] = hypot(x[i] - x[j], y[i] - y[j]); + dist[i][j] = hypot(v[i].fi - v[j].fi, v[i].se - v[j].se); - fill(dp[0], dp[0] + 101 * 2100, 1e9); + fill(dp[0], dp[0] + (MAX * (1 << MAXT)), 1e9); for (int i = 0; i < k; ++i) - dp[i][1<<i] = 0; + dp[i][1 << i] = 0; - for (int mask = 0; mask < (1 << k); ++mask) { + for (int mask = 1; mask < (1 << k); ++mask) { for (int i = 0; i < n; ++i) for (int ss = mask; ss > 0; ss = (ss - 1) & mask) - dp[i][mask] = min(dp[i][mask], dp[i][ss] + dp[i][mask - ss]); + dp[i][mask] = min(dp[i][mask], dp[i][ss] + dp[i][mask ^ ss]); for (int i = 0; i < n; ++i) for (int j = k; j < n; ++j) - dp[j][mask] = min(dp[j][mask], dp[i][mask] + graph[i][j]); + dp[j][mask] = min(dp[j][mask], dp[i][mask] + dist[i][j]); } - + double ans = 1e9; - for (int i = k; i < n; ++i) + for (int i = 0; i < n; ++i) ans = min(ans, dp[i][(1 << k) - 1]); cout << ans << ende; return 0; diff --git a/contests/SBC18/L.cpp b/contests/SBC18/L.cpp index e0452563d414cd91d0012b04674faaa5b18eb490..49872438e144ee0f8a4736b387a3d12dfd2cd118 100644 --- a/contests/SBC18/L.cpp +++ b/contests/SBC18/L.cpp @@ -1,14 +1,14 @@ #include <bits/stdc++.h> #define MAX 101010 -#define MOD 1000000007 +#define MLOG 17 #define EPS 1e-6 +#define MOD 1000000007 #define inf 0x3f3f3f3f #define llinf 0x3f3f3f3f3f3f3f3f #define fi first #define se second -#define sz size() #define pb push_back #define ende '\n' @@ -18,116 +18,83 @@ using namespace std; -typedef long long ll; -typedef pair<int,int> ii; +using ll = long long; +using ii = pair<int,int>; int h[MAX]; -int par[MAX][20]; +int par[MAX][MLOG]; vector<int> graph[MAX]; - -void dfs(int v, int p = -1) { - par[v][0] = p; +void dfs(int x, int p) { + par[x][0] = p; if (p != -1) - h[v] = h[p] + 1; + h[x] = h[p] + 1; - for (int i = 1; i < 20; ++i) - if (par[v][i-1] != -1) - par[v][i] = par[par[v][i-1]][i-1]; + for (int i = 1; i < MLOG; ++i) + if (par[x][i-1] != -1) + par[x][i] = par[par[x][i-1]][i-1]; - for (auto u : graph[v]) - if (p != u) - dfs(u, v); + for (auto i : graph[x]) + if (i != p) + dfs(i, x); } +int lca(int a, int b) { + if (h[a] < h[b]) + swap(a, b); -int lca(int p, int q) { - if (h[p] < h[q]) - swap(p, q); + for (int i = MLOG - 1; i >= 0; --i) + if (par[a][i] != -1 && h[par[a][i]] >= h[b]) + a = par[a][i]; - for (int i = 19; i >= 0; --i) - if (par[p][i] != -1 and h[par[p][i]] >= h[q]) - p = par[p][i]; + if (a == b) + return a; - if (p == q) - return p; - - for (int i = 19; i >= 0; --i) - if (par[p][i] != -1 and par[p][i] != par[q][i]) { - p = par[p][i]; - q = par[q][i]; + for (int i = MLOG - 1; i >= 0; --i) + if (par[a][i] != -1 && par[a][i] != par[b][i]) { + a = par[a][i]; + b = par[b][i]; } - return par[p][0]; + return par[a][0]; } - int main() { ios::sync_with_stdio(0); cin.tie(0); - int a, b, c, d; int n, q; cin >> n >> q; for (int i = 0; i < n - 1; ++i) { - cin >> a >> b; + int a, b; cin >> a >> b; a--, b--; graph[a].pb(b); graph[b].pb(a); } + mset(h, 0); mset(par, -1); - dfs(1); + dfs(0, -1); for (int i = 0; i < q; ++i) { - cin >> a >> b >> c >> d; - - int lab = lca(a, b); - int lac = lca(a, c); - int lad = lca(a, d); - int lbc = lca(b, c); - int lbd = lca(b, d); - int lcd = lca(c, d); - - // If path C->D is above (or different subtree) than A->B and has no intersection - if (h[lca(c, lab)] < h[lab] and h[lca(d, lab)] < h[lab]) - cout << 0 << ende; - - // If path A->B is above (or different subtree) than C->D and has no intersection - else if (h[lca(a, lcd)] < h[lcd] and h[lca(b, lcd)] < h[lcd]) - cout << 0 << ende; - - // There is an intersection - else { - - // If lca(A, B) belongs to the path C->D - if (h[lcd] < h[lab]) { - - // If intersection occurs between C->lca(C,D) - if (h[lac] > h[lcd] or h[lbc] > h[lcd]) cout << abs(h[lca(lac, c)] - h[lca(lbc, c)]) + 1 << ende; - - // If intersection occurs between D->lca(C,D) - else cout << abs(h[lca(lad, d)] - h[lca(lbd, d)]) + 1 << ende; - - - // If lca(C, D) belongs to the path A->B - } else if (h[lab] < h[lcd]) { - - // If intersection occurs between A->lca(A,B) - if (h[lac] > h[lab] or h[lad] > h[lab]) cout << abs(h[lca(lac, a)] - h[lca(lad, a)]) + 1 << ende; - - // If intersection occurs between B->lca(A,B) - else cout << abs(h[lca(lbc, b)] - h[lca(lbd, b)]) + 1 << ende; - - - // It means that lca(A, B) is the same node as lca(C, D) - } else { - - // If A and C are on the same side -> B and D are on the same side - if (h[lac] > h[lcd] or h[lbd] > h[lcd]) cout << (h[lac] - h[lcd]) + (h[lbd] - h[lcd]) + 1 << ende; - - // If A and D are on the same side -> B and C are on the same side - else cout << (h[lad] - h[lcd]) + (h[lbc] - h[lcd]) + 1 << ende; - } + int a, b, c, d; + cin >> a >> b >> c >> d; a--, b--, c--, d--; + vector<int> v = { lca(a, c), lca(a, d), lca(b, c), lca(b, d) }; + + sort(all(v), [&](int a, int b) { + return h[a] > h[b]; + }); + + if (v[0] == v[1]) { + bool t1 = ((lca(a, v[0]) == v[0] || lca(b, v[0]) == v[0]) && h[lca(a, b)] <= h[v[0]]); + bool t2 = ((lca(c, v[0]) == v[0] || lca(d, v[0]) == v[0]) && h[lca(c, d)] <= h[v[0]]); + cout << (t1 && t2) << ende; + } else { + int aux = lca(v[0], v[1]); + + if (aux == v[0] || aux == v[1]) + cout << abs(h[v[0]] - h[v[1]]) + 1 << ende; + else + cout << (h[v[0]] - h[aux] + 1) + (h[v[1]] - h[aux] + 1) - 1 << ende; } }