Submission #282626

#TimeUsernameProblemLanguageResultExecution timeMemory
282626rama_pangPark (JOI17_park)C++14
100 / 100
848 ms1252 KiB
#include "park.h"
#include <bits/stdc++.h>
using namespace std;

void Detect(int T, int N) {
  vector<int> graph;
  vector<int> candidate;
  vector<pair<int, int>> edges;

  graph.emplace_back(0);
  for (int i = 1; i < N; i++) {
    candidate.emplace_back(i);
  }

  const auto CreateVector = [&](int l, int r, vector<int> a) {
    vector<int> res;
    for (int i = l; i <= r; i++) {
      res.emplace_back(a[i]);
    }
    return res;
  };

  const auto IsConnected = [&](int node, vector<int> g) -> bool {
    vector<int> query(N, 0);
    for (auto i : g) {
      query[i] = 1;
    }
    query[node] = 1;
    return Ask(min(g[0], node), max(g[0], node), query.data());
  };

  const auto IsConnectedTrough = [&](int node, vector<int> g, vector<int> add) -> bool {
    vector<int> query(N, 0);
    for (auto i : g) {
      query[i] = 1;
    }
    for (auto i : add) {
      query[i] = 1;
    }
    query[node] = 1;
    return Ask(min(g[0], node), max(g[0], node), query.data());
  };

  function<void(int, vector<int>)> Connect = [&](int node, vector<int> g) -> void {
    if (g.empty()) return;
    vector<vector<int>> adj(N);
    vector<int> active(N);
    for (auto i : g) {
      active[i] = 1;
    }
    for (auto e : edges) {
      if (active[e.first] && active[e.second]) {
        adj[e.first].emplace_back(e.second);
        adj[e.second].emplace_back(e.first);
      }
    }

    vector<int> vis;
    vector<int> invis(N, 0);
    vis.emplace_back(g[0]);
    invis[g[0]] = 1;
    for (int ptr = 0; ptr < (int) vis.size(); ptr++) {
      int u = vis[ptr];
      for (auto v : adj[u]) {
        if (!invis[v]) {
          invis[v] = 1;
          vis.emplace_back(v);
        }
      }
    }

    if (vis.size() != g.size()) {
      vector<int> p1, p2;
      for (auto i : g) {
        if (invis[i]) {
          p1.emplace_back(i);
        } else {
          p2.emplace_back(i);
        }
      }
      Connect(node, p1);
      Connect(node, p2);
      return;
    }

    if (!IsConnected(node, CreateVector(0, int(vis.size()) - 1, vis))) {
      return;
    }

    int lo = 0, hi = int(vis.size()) - 1;
    while (lo < hi) {
      int md = (lo + hi) / 2;
      if (IsConnected(node, CreateVector(0, md, vis))) {
        hi = md;
      } else {
        lo = md + 1;
      }
    }
    edges.emplace_back(node, vis[lo]);
    g.erase(find(begin(g), end(g), vis[lo]));
    return Connect(node, g);
  };

  while (!candidate.empty()) {
    int node = candidate.back();
    vector<int> path;
    function<void(int, int)> FindPath = [&](int l, int r) {
      vector<int> c;
      if (l == 0) {
        c = graph;
      } else {
        c = {l};
      }
      if (IsConnected(r, c)) {
        path.emplace_back(r);
      } else {
        // Find a node on path from l to r
        int lo = 0, hi = int(candidate.size()) - 1;
        while (lo < hi) {
          int md = (lo + hi) / 2;
          if (IsConnectedTrough(r, c, CreateVector(0, md, candidate))) {
            hi = md;
          } else {
            lo = md + 1;
          }
        }
        FindPath(l, candidate[lo]);
        FindPath(candidate[lo], r);
      }
    };

    FindPath(0, node);
    for (auto u : path) {
      Connect(u, graph);
      graph.emplace_back(u);
      candidate.erase(find(begin(candidate), end(candidate), u));
    }
  }

  for (auto e : edges) {
    Answer(min(e.first, e.second), max(e.first, e.second));
  }
}
#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...