Advertisement
volochai

CCO Training Contest 4 Three Nodes

Apr 26th, 2024
735
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.76 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. #include <chrono>
  3.  
  4. #pragma GCC optimize("Ofast")
  5. #pragma GCC optimize("unroll-loops")
  6. #pragma GCC target("avx,avx2")
  7.  
  8. #define ll long long
  9. #define all(x) (x).begin(), (x).end()
  10. #define rall(x) (x).rbegin(), (x).rend()
  11. #define watch(x) cout << (#x) << " : " << x << '\n'
  12. #define boost ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  13.  
  14. using namespace std;
  15. using namespace chrono;
  16.  
  17. mt19937 rnd(steady_clock::now().time_since_epoch().count());
  18.  
  19. const int N = 3e5 + 128;
  20. const int LOG = 18;
  21. vector <int> g[N];
  22. int n;
  23. int dp[N]; // limit.
  24. int h[N], vert[N];
  25. int tin[N], tout[N];
  26. int timer;
  27. int nxt[N][LOG];
  28. int lift[N][LOG];
  29. int to[N][3];
  30. int upv[N], dir[N];
  31. int ans[N][3];
  32. int x[N], y[N], z[N];
  33. pair <int, int> sum[4 * N];
  34. int add[4 * N];
  35.  
  36. void bld(int v, int tl, int tr) {
  37.     if (tl == tr) {
  38.         sum[v] = make_pair(h[vert[tl]], vert[tl]);
  39.         return;
  40.     }
  41.     int tm = (tl + tr) >> 1;
  42.     bld(v << 1, tl, tm);
  43.     bld(v << 1 | 1, tm + 1, tr);
  44.     sum[v] = max(sum[v << 1], sum[v << 1 | 1]);
  45. }
  46.  
  47. void apply(int v, int tl, int tr, int x) {
  48.     sum[v].first += x;
  49.     add[v] += x;
  50. }
  51.  
  52. void push(int v, int tl, int tr) {
  53.     if (add[v] == 0)
  54.         return;
  55.     int tm = (tl + tr) >> 1;
  56.     apply(v << 1, tl, tm, add[v]);
  57.     apply(v << 1 | 1, tm + 1, tr, add[v]);
  58.     add[v] = 0;
  59. }
  60.  
  61. void update(int l, int r, int x, int v, int tl, int tr) {
  62.     if (tl > r || tr < l)
  63.         return;
  64.     push(v, tl, tr);
  65.     if (l <= tl && tr <= r) {
  66.         apply(v, tl, tr, x);
  67.         return;
  68.     }
  69.     int tm = (tl + tr) >> 1;
  70.     update(l, r, x, v << 1, tl, tm);
  71.     update(l, r, x, v << 1 | 1, tm + 1, tr);
  72.     sum[v] = max(sum[v << 1], sum[v << 1 | 1]);
  73. }
  74.  
  75. pair <int, int> get_max(int l, int r, int v, int tl, int tr) {
  76.     if (tl > r || tr < l)
  77.         return make_pair(-1, -1);
  78.     push(v, tl, tr);
  79.     if (l <= tl && tr <= r)
  80.         return sum[v];
  81.     int tm = (tl + tr) >> 1;
  82.     return max(get_max(l, r, v << 1, tl, tm),
  83.                 get_max(l, r, v << 1 | 1, tm + 1, tr));
  84. }
  85.  
  86. vector < pair<int, int> > C[N];
  87.  
  88. struct max_path {
  89.     int max_dist, pt;
  90.     bool iup;
  91.  
  92.     max_path() {
  93.         max_dist = 0;
  94.         pt = -1;
  95.         iup = false;
  96.     }
  97. };
  98.  
  99. struct st {
  100.     vector <max_path> cur;
  101.  
  102.     int v;
  103.  
  104.     bool operator < (const st& other) const {
  105.         assert((int)cur.size() == (int)other.cur.size());
  106.         for (int c = 0; c < 3; c++)
  107.             if (cur[c].max_dist != other.cur[c].max_dist)
  108.                 return cur[c].max_dist < other.cur[c].max_dist;
  109.         return v < other.v;
  110.     };
  111.  
  112.     st() {
  113.         cur.clear();
  114.         v = -1;
  115.     }
  116. };
  117.  
  118. int get(int v, int k) {
  119.     for (int b = 0; b < LOG; b++)
  120.         if ((k >> b) & 1)
  121.             v = lift[v][b];
  122.     return v;
  123. }
  124.  
  125. int get_lca(int u, int v) {
  126.     if (h[v] > h[u])
  127.         swap(u, v);
  128.     int k = h[u] - h[v];
  129.     u = get(u, k);
  130.     if (u == v)
  131.         return u;
  132.     for (int b = LOG - 1; b >= 0; b--)
  133.         if (lift[v][b] != lift[u][b])
  134.             v = lift[v][b], u = lift[u][b];
  135.     return lift[v][0];
  136. }
  137.  
  138. int get_dist(int u, int v) {
  139.     return h[u] + h[v] - 2 * h[get_lca(u, v)];
  140. }
  141.  
  142. vector < st > options;
  143.  
  144. void dfs(int v, int p = 1) {
  145.     if (v != 1)
  146.         h[v] = h[p] + 1;
  147.  
  148.     tin[v] = timer++;
  149.     vert[tin[v]] = v;
  150.  
  151.     lift[v][0] = p;
  152.     for (int b = 1; b < LOG; b++)
  153.         lift[v][b] = lift[lift[v][b - 1]][b - 1];
  154.  
  155.     for (auto& to : g[v])
  156.         if (to != p)
  157.             dfs(to, v);
  158.  
  159.     tout[v] = timer - 1;
  160. }
  161.  
  162. void go(int v, int p = -1) {
  163.     vector < pair<int, int> >  values;
  164.     for (auto& to : g[v])
  165.         if (to != p) {
  166.             values.push_back(get_max(tin[to], tout[to], 1, 0, n - 1));
  167.             update(0, n - 1, +1, 1, 0, n - 1);
  168.             update(tin[to], tout[to], -2, 1, 0, n - 1);
  169.             go(to, v);
  170.             update(0, n - 1, -1, 1, 0, n - 1);
  171.             update(tin[to], tout[to], +2, 1, 0, n - 1);
  172.         }
  173.  
  174.     if (tin[v] > 0)
  175.         values.push_back(get_max(0, tin[v] - 1, 1, 0, n - 1));
  176.     if (tout[v] + 1 < n)
  177.         values.push_back(get_max(tout[v] + 1, n - 1, 1, 0, n - 1));
  178.  
  179.     sort(rall(values));
  180.  
  181.     st x;
  182.     x.v = v;
  183.  
  184.     bool was_up = false;
  185.     for (auto& [dist, vertex] : values) {
  186.         if ((int)x.cur.size() == 3)
  187.             break;
  188.         bool needUp = (get_lca(vertex, v) != v);
  189.         if (needUp && was_up)
  190.             continue;
  191.         max_path maxi;
  192.         if (needUp) {
  193.             was_up = true;
  194.             maxi.iup = true;
  195.         } else {
  196.             if (!nxt[v][0])
  197.                 nxt[v][0] = get(vertex, h[vertex] - h[v] - 1);
  198.         }
  199.         maxi.max_dist = dist;
  200.         maxi.pt = vertex;
  201.         x.cur.push_back(maxi);
  202.     }
  203.  
  204.     options.push_back(x);
  205. }
  206.  
  207. pair <int, int> mx[4 * N];
  208.  
  209. void build(int v, int tl, int tr) {
  210.     mx[v] = make_pair(-1, -1);
  211.     if (tl == tr)
  212.         return;
  213.     int tm = (tl + tr) >> 1;
  214.     build(v << 1, tl, tm);
  215.     build(v << 1 | 1, tm + 1, tr);
  216. }
  217.  
  218. void update(int pos, pair<int, int> val, int v, int tl, int tr) {
  219.     if (tl > pos || tr < pos)
  220.         return;
  221.     if (tl == tr) {
  222.         mx[v] = max(mx[v], val);
  223.         return;
  224.     }
  225.     int tm = (tl + tr) >> 1;
  226.     update(pos, val, v << 1, tl, tm);
  227.     update(pos, val, v << 1 | 1, tm + 1, tr);
  228.     mx[v] = max(mx[v << 1], mx[v << 1 | 1]);
  229. }
  230.  
  231. pair <int, int> get(int l, int r, int v, int tl, int tr) {
  232.     if (tl > r || tr < l)
  233.         return make_pair(-1, -1);
  234.     if (l <= tl && tr <= r)
  235.         return mx[v];
  236.     int tm = (tl + tr) >> 1;
  237.     return max(get(l, r, v << 1, tl, tm),
  238.                 get(l, r, v << 1 | 1, tm + 1, tr));
  239. }
  240.  
  241. void solve() {
  242.     cin >> n;
  243.     for (int i = 1; i < n; i++) {
  244.         int u = i + 1, v = rnd() % i + 1;
  245.         cin >> u >> v;
  246.         g[u].push_back(v);
  247.         g[v].push_back(u);
  248.     }
  249.  
  250.     dfs(1);
  251.  
  252.     bld(1, 0, n - 1);
  253.  
  254.     go(1);
  255.  
  256.     sort(all(options), [&](const auto& x, const auto& y) -> bool {
  257.         return x.v < y.v;
  258.     });
  259.  
  260.     for (int b = 1; b < LOG; b++)
  261.         for (int v = 1; v <= n; v++)
  262.             nxt[v][b] = nxt[nxt[v][b - 1]][b - 1];
  263.  
  264.     for (auto& x : options)
  265.         while ((int)x.cur.size() < 3)
  266.             x.cur.push_back(max_path());
  267.  
  268.     sort(rall(options));
  269.  
  270.     int q;
  271.     cin >> q;
  272.  
  273.     for (int i = 0; i < q; i++) {
  274.         cin >> x[i] >> y[i] >> z[i];
  275.         assert((x[i] + y[i] - z[i]) % 2 == 0);
  276.         C[i].push_back(make_pair((x[i] + y[i] - z[i]) / 2, 0));
  277.         assert((x[i] - y[i] + z[i]) % 2 == 0);
  278.         C[i].push_back(make_pair((x[i] - y[i] + z[i]) / 2, 1));
  279.         assert((y[i] + z[i] - x[i]) % 2 == 0);
  280.         C[i].push_back(make_pair((y[i] + z[i] - x[i]) / 2, 2));
  281.  
  282.         sort(rall(C[i]));
  283.     }
  284.  
  285.     vector <int> order(q);
  286.     iota(all(order), 0);
  287.  
  288.     sort(all(order), [&](const int& x, const int& y) -> bool {
  289.         for (int c = 0; c < 3; c++)
  290.             if (C[x][c].first != C[y][c].first)
  291.                 return C[x][c].first > C[y][c].first;
  292.         return x < y;
  293.     });
  294.  
  295.     int p0 = -1;
  296.  
  297.     build(1, 0, N);
  298.  
  299.     for (int c = 0; c < q; c++) {
  300.         int v = order[c];
  301.         while (p0 + 1 < n && options[p0 + 1].cur[0].max_dist >= C[v][0].first) {
  302.             ++p0;
  303.             update(options[p0].cur[1].max_dist, make_pair(options[p0].cur[2].max_dist, p0), 1, 0, N);
  304.         }
  305.  
  306.         auto [value, pos] = get(C[v][1].first, N, 1, 0, N);
  307.         assert(value >= C[v][2].first);
  308.  
  309.         for (int c = 0; c < 3; c++) {
  310.             auto [dist, ix] = C[v][c];
  311.  
  312.             if (dist == 0) {
  313.                 ans[v][ix] = options[pos].v;
  314.                 continue;
  315.             }
  316.  
  317.             if (options[pos].cur[c].iup) {
  318.                 int x = get_lca(options[pos].v, options[pos].cur[c].pt);
  319.                 if (dist <= h[options[pos].v] - h[x]) {
  320.                     ans[v][ix] = get(options[pos].v, dist);
  321.                 } else {
  322.                     dist -= h[options[pos].v] - h[x];
  323.                     int tx = get(options[pos].cur[c].pt, h[options[pos].cur[c].pt] - h[x] - 1);
  324.                     dist--;
  325.                     for (int b = 0; b < LOG; b++)
  326.                         if ((dist >> b) & 1)
  327.                             tx = nxt[tx][b];
  328.                     ans[v][ix] = tx;
  329.                 }
  330.             } else {
  331.                 int tx = get(options[pos].cur[c].pt, h[options[pos].cur[c].pt] - h[options[pos].v] - 1);
  332.                 dist--;
  333.                 for (int b = 0; b < LOG; b++)
  334.                     if ((dist >> b) & 1)
  335.                         tx = nxt[tx][b];
  336.                 ans[v][ix] = tx;
  337.             }
  338.         }
  339.     }
  340.  
  341.     for (int i = 0; i < q; i++)
  342.         for (int c = 0; c < 3; c++)
  343.             cout << ans[i][c] << " \n"[c + 1 == 3];
  344.  
  345. }
  346.  
  347. main() {
  348.     boost;
  349.     solve();
  350.     return 0;
  351. }
  352.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement