Submission #1241150

#TimeUsernameProblemLanguageResultExecution timeMemory
1241150kunzaZa183Werewolf (IOI18_werewolf)C++20
100 / 100
1222 ms237388 KiB
#include <bits/stdc++.h>
using namespace std;

vector<int> check_validity(int N, vector<int> X, vector<int> Y, vector<int> S,
                           vector<int> E, vector<int> L, vector<int> R) {
  vector<pair<int, int>> vpii;
  for (int i = 0; i < X.size(); i++)
    vpii.push_back(minmax(X[i], Y[i]));
  vector<array<int, 5>> vai5;
  for (int i = 0; i < S.size(); i++)
    vai5.push_back({i, S[i], E[i], L[i], R[i]});

  function<int(int, vector<int> &)> fvivi = [&](int cur, vector<int> &par) {
    if (par[cur] == cur)
      return cur;
    return par[cur] = fvivi(par[cur], par);
  };

  int ct = -1;
  function<void(int, vector<vector<int>> &, vector<int> &, vector<int> &)> dfs =
      [&](int cur, vector<vector<int>> &adj, vector<int> &l, vector<int> &r) {
        if (adj[cur].empty()) {
          ct++;
          l[cur] = r[cur] = ct;
          return;
        }
        l[cur] = ct + 1;
        for (auto a : adj[cur])
          dfs(a, adj, l, r);
        r[cur] = ct;
      };

  sort(vpii.begin(), vpii.end(),
       [&](pair<int, int> a, pair<int, int> b) { return a.first > b.first; });

  vector<int> parvi1(N);
  iota(parvi1.begin(), parvi1.end(), 0);

  vector<vector<int>> adj1(N);
  for (auto [a, b] : vpii) {
    a = fvivi(a, parvi1), b = fvivi(b, parvi1);
    parvi1[a] = parvi1[b] = adj1.size();
    parvi1.push_back(parvi1.size());

    adj1.push_back({});
    adj1.back().push_back(a);
    if (a != b)
      adj1.back().push_back(b);
  }

  vector<int> l1(parvi1.size()), r1(parvi1.size());
  dfs(parvi1.size() - 1, adj1, l1, r1);

  parvi1 = vector<int>(N);
  iota(parvi1.begin(), parvi1.end(), 0);
  int in = 0;
  sort(vai5.begin(), vai5.end(),
       [&](array<int, 5> a, array<int, 5> b) { return a[3] > b[3]; });
  vector<int> ql1(S.size()), qr1(S.size());
  for (auto [a, b] : vpii) {
    while (in < vai5.size() && vai5[in][3] > a) {
      ql1[vai5[in][0]] = l1[fvivi(vai5[in][1], parvi1)],
      qr1[vai5[in][0]] = r1[fvivi(vai5[in][1], parvi1)];
      in++;
    }

    a = fvivi(a, parvi1), b = fvivi(b, parvi1);
    parvi1[a] = parvi1[b] = parvi1.size();
    parvi1.push_back(parvi1.size());
  }

  while (in < vai5.size()) {
    ql1[vai5[in][0]] = l1[fvivi(vai5[in][1], parvi1)],
    qr1[vai5[in][0]] = r1[fvivi(vai5[in][1], parvi1)];
    in++;
  }

  vector<int> parvi2(N);
  iota(parvi2.begin(), parvi2.end(), 0);

  sort(vpii.begin(), vpii.end(),
       [&](pair<int, int> a, pair<int, int> b) { return a.second < b.second; });

  vector<vector<int>> adj2(N);
  for (auto [a, b] : vpii) {
    a = fvivi(a, parvi2), b = fvivi(b, parvi2);
    parvi2[a] = parvi2[b] = adj2.size();
    parvi2.push_back(parvi2.size());

    adj2.push_back({});
    adj2.back().push_back(a);
    if (a != b)
      adj2.back().push_back(b);
  }

  vector<int> l2(parvi2.size()), r2(parvi2.size());
  ct = -1;
  dfs(parvi2.size() - 1, adj2, l2, r2);

  parvi2 = vector<int>(N);
  iota(parvi2.begin(), parvi2.end(), 0);
  in = 0;
  sort(vai5.begin(), vai5.end(),
       [&](array<int, 5> a, array<int, 5> b) { return a[4] < b[4]; });
  vector<int> ql2(S.size()), qr2(S.size());
  for (auto [a, b] : vpii) {
    while (in < vai5.size() && vai5[in][4] < b) {
      ql2[vai5[in][0]] = l2[fvivi(vai5[in][2], parvi2)],
      qr2[vai5[in][0]] = r2[fvivi(vai5[in][2], parvi2)];
      in++;
    }

    a = fvivi(a, parvi2), b = fvivi(b, parvi2);
    parvi2[a] = parvi2[b] = parvi2.size();
    parvi2.push_back(parvi2.size());
  }

  while (in < vai5.size()) {
    ql2[vai5[in][0]] = l2[fvivi(vai5[in][2], parvi2)],
    qr2[vai5[in][0]] = r2[fvivi(vai5[in][2], parvi2)];
    in++;
  }

  vector<array<int, 3>> order(N);
  vector<pair<int, int>> points(N);
  for (int i = 0; i < N; i++)
    points[i] = {l1[i], l2[i]};
  sort(points.begin(), points.end());
  for (int i = 0; i < N; i++)
    order[i] = {i, points[i].first, points[i].second};
  auto ocmp = [&](array<int, 3> a, array<int, 3> b) { return a[2] < b[2]; };
  sort(order.begin(), order.end(), ocmp);

  vector<int> ans(L.size());

  struct node {
    int ct = 0;
    node *l = NULL, *r = NULL;
  };

  vector<node *> vn;

  function<node *(int, int)> build = [&](int curl, int curr) {
    auto tmp = new node;
    if (curl == curr) {
      return tmp;
    }
    int mid = (curl + curr) / 2;
    tmp->l = build(curl, mid), tmp->r = build(mid + 1, curr);
    return tmp;
  };

  vn.push_back(build(0, N - 1));

  function<node *(node *, int, int, int)> insert = [&](node *n, int curl,
                                                       int curr, int in) {
    auto tmp = new node;
    if (curl == curr) {
      tmp->ct = 1;
      return tmp;
    }
    int mid = (curl + curr) / 2;
    if (in <= mid) {
      tmp->r = n->r;
      tmp->l = insert(n->l, curl, mid, in);
    } else {
      tmp->l = n->l;
      tmp->r = insert(n->r, mid + 1, curr, in);
    }
    tmp->ct = tmp->l->ct + tmp->r->ct;
    return tmp;
  };

  for (auto [in, x, y] : order) {
    vn.push_back(insert(vn.back(), 0, N - 1, in));
  }

  int ql, qr;
  function<int(node *, int, int)> qry = [&](node *n, int curl, int curr) {
    if (curl > qr || curr < ql)
      return 0;
    if (ql <= curl && curr <= qr)
      return n->ct;

    return qry(n->l, curl, (curl + curr) / 2) +
           qry(n->r, (curl + curr) / 2 + 1, curr);
  };

  for (int i = 0; i < S.size(); i++) {
    ql = lower_bound(points.begin(), points.end(), make_pair(ql1[i], -1)) -
            points.begin(),
        qr = upper_bound(points.begin(), points.end(),
                        make_pair(qr1[i], INT_MAX)) -
            points.begin() - 1;

    int l = lower_bound(order.begin(), order.end(),
                         array<int, 3>({-1, -1, ql2[i]}), ocmp) -
             order.begin(),
        r = upper_bound(order.begin(), order.end(),
                         array<int, 3>({-1, -1, qr2[i]}), ocmp) -
             order.begin();

    ans[i] = min(1, qry(vn[r], 0, N - 1) - qry(vn[l], 0, N - 1));
  }

  return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...