Submission #317493

#TimeUsernameProblemLanguageResultExecution timeMemory
317493kdh9949Simurgh (IOI17_simurgh)C++17
100 / 100
125 ms8312 KiB
#include "simurgh.h"
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;

using vint = vector<int>;
using vll = vector<ll>;
using vld = vector<ld>;
using vpii = vector<pii>;
using vpil = vector<pil>;
using vpli = vector<pli>;
using vpll = vector<pll>;

#define x first
#define y second
#define all(v) v.begin(),v.end()

vint find_roads(int n, vint u, vint v) {
  int m = u.size();

  vector<vpii> e(n);
  for(int i = 0; i < m; i++) {
    e[u[i]].emplace_back(v[i], i);
    e[v[i]].emplace_back(u[i], i);
  }

  vint ord(n), low(n), tv;
  vpii par(n);
  vector<vpii> te(n), be(n);
  function<void(int, int)> f = [&](int x, int y) {
    static int cnt = 0;
    ord[x] = low[x] = ++cnt;
    for(pii &p : e[x]) {
      if(y == p.x) par[x] = p;
      else if(!ord[p.x]) {
        f(p.x, x);
        te[x].push_back(p);
        tv.push_back(p.y);
        low[x] = min(low[x], low[p.x]);
      }
      else if(ord[x] > ord[p.x]) {
        be[x].push_back(p);
        low[x] = min(low[x], ord[p.x]);
      }
    }
  };
  f(0, 0);

  auto rep1 = [&](int x, int y) {
    vint v = tv;
    *find(all(v), x) = y;
    return v;
  };

  int T = count_common_roads(tv);
  vint ans(m, -1);
  function<void(int)> g = [&](int x) {
    for(pii &p : te[x]) g(p.x);
    if(x && low[x] == ord[x]) {
      ans[par[x].y] = 1;
      return;
    }
    if(be[x].empty()) return;
    sort(all(be[x]), [&](pii &p, pii &q) {
      return ord[p.x] > ord[q.x];
    });
    pii B = be[x].back();
    if(ans[par[x].y] >= 0) {
      ans[B.y] = count_common_roads(rep1(par[x].y, B.y)) - T + ans[par[x].y];
      for(int t = par[x].x; t != B.x; t = par[t].x) {
        if(ans[par[t].y] < 0)
          ans[par[t].y] = T - count_common_roads(rep1(par[t].y, B.y)) + ans[B.y];
      }
    }
    else {
      int mn = 0, mx = 0;
      for(int t = x; t != B.x; t = par[t].x) {
        ans[par[t].y] = count_common_roads(rep1(par[t].y, B.y)) - T;
        mn = min(mn, ans[par[t].y]);
        mx = max(mx, ans[par[t].y]);
      }
      ans[B.y] = mx;
      if(mn < mx) {
        for(int t = x; t != B.x; t = par[t].x) ans[par[t].y] = mx - ans[par[t].y];
      }
    }
    be[x].pop_back();
  };
  g(0);

  vint chk(m), val(m);
  int ts = 0;
  function<void(vint&, vint&, int, int, int)> h =
  [&](vint &v, vint &w, int s, int e, int c) {
    if(c == 0 || c == e - s + 1) {
      for(int i = s; i <= e; i++) ans[v[i]] = !!c;
      return;
    }
    ts++;
    int m = (s + e) / 2;
    for(int i = s; i <= m; i++) {
      chk[w[i]] = ts;
      val[w[i]] = v[i];
    }
    vint cv = tv;
    int ofs = 0;
    for(int &x : cv) if(chk[x] == ts) {
      ofs += ans[x];
      x = val[x];
    }
    int lc = count_common_roads(cv) - T + ofs;
    h(v, w, s, m, lc);
    h(v, w, m + 1, e, c - lc);
  };

  for(int x = 1; x < n; x++) {
    if(be[x].empty()) continue;
    vint v, w;
    int sz = be[x].size();
    for(int i = 0, t = x; i < sz; i++) {
      v.push_back(be[x][i].y);
      w.push_back(par[t].y);
      t = be[x][i].x;
    }

    ts++;
    for(int i = 0; i < sz; i++) {
      chk[w[i]] = ts;
      val[w[i]] = v[i];
    }
    vint cv = tv;
    int ofs = 0;
    for(int &y : cv) if(chk[y] == ts) {
      ofs += ans[y];
      y = val[y];
    }
    h(v, w, 0, sz - 1, count_common_roads(cv) - T + ofs);
  }

  vint ret;
  for(int i = 0; i < m; i++) if(ans[i]) ret.push_back(i);
  return ret;
}
#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...