Submission #1152213

#TimeUsernameProblemLanguageResultExecution timeMemory
1152213julia_08Parachute rings (IOI12_rings)C++20
100 / 100
528 ms77188 KiB
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1e6 + 10;

int pai[MAXN][5], sz[MAXN][5];

int deg[MAXN];

int good[MAXN], ciclo[5];

int ciclo_geral[MAXN], init[MAXN];

int adj[MAXN][3];

int sz_ciclo = 0;

bool ok = true;

int n;

int get(int v, int x){
  if(v == pai[v][x]) return v;
  return pai[v][x] = get(pai[v][x], x);
}

void dsu_union(int a, int b, int x){

  a = get(a, x);
  b = get(b, x);

  if(sz[a][x] > sz[b][x]) swap(a, b);

  pai[a][x] = b;
  sz[b][x] += sz[a][x];
}

vector<pair<int, int>> edges;

vector<int> cand;

int cnt_4 = 0, cnt_3 = 0;

int cnt_ciclo = 0;

void dsu_init(int x){

  if(init[cand[x]]) return;

  init[cand[x]] = 1;

  for(int i=0; i<n; i++) pai[i][x] = i, sz[i][x] = 1;

  ciclo[x] = 0;

  for(auto [a, b] : edges){

    if(a == cand[x] || b == cand[x]) continue;

    if(get(a, x) != get(b, x)) dsu_union(a, b, x);
    else ciclo[x] = 1;

  }

}

void Init(int n_){

  n = n_;

  ok = true;

  cand.clear();
  edges.clear();

  for(int j=0; j<5; j++){

    for(int i=0; i<n; i++) pai[i][j] = i, sz[i][j] = 1;

    ciclo[j] = 0;
  }

  for(int i=0; i<n; i++){

    deg[i] = 0;
    good[i] = 1;
    ciclo_geral[i] = 0;

    cand.push_back(i);
  }

  cnt_3 = cnt_4 = cnt_ciclo = 0;

}

void check_4(int v){

  assert((int) cand.size() <= 4); // passou pelo check_3 em algum momento

  for(auto x : cand) if(x != v) good[x] = 0;

  cand.clear();

  if(good[v]){
    cand.push_back(v);
    dsu_init(0);
  }
}

void check_3(int v){

  vector<int> to_add;

  if(good[v]) to_add.push_back(v);

  for(int i=0; i<deg[v]; i++) if(good[adj[v][i]]) to_add.push_back(adj[v][i]);

  for(auto x : cand) good[x] = 0;

  cand.clear();

  for(auto x : to_add){
    cand.push_back(x);
    good[x] = 1;
    dsu_init(cand.size() - 1);
  }

  assert((int) cand.size() <= 4);
}

void Link(int a, int b){

  if(!ok) return;

  deg[a] ++, deg[b] ++;

  if(deg[a] <= 3) adj[a][deg[a] - 1] = b;
  if(deg[b] <= 3) adj[b][deg[b] - 1] = a;

  if(deg[a] == 4) cnt_4 ++;
  if(deg[b] == 4) cnt_4 ++;

  if(deg[a] == 3) cnt_3 ++;
  if(deg[b] == 3) cnt_3 ++;

  if(cnt_4 > 1){
    for(auto x : cand) good[x] = 0;
    cand.clear();

    ok = false;

    return;
  }

  if(deg[a] == 4) check_4(a);
  if(deg[b] == 4) check_4(b);

  if(!ok) return;

  if(deg[a] == 3) check_3(a);
  if(deg[b] == 3) check_3(b);

  // cand atualizado!

  edges.push_back({a, b});

  if(cnt_3 > 0){

    assert((int) cand.size() <= 4);

    for(int i=0; i<(int) cand.size(); i++){

      if(a == cand[i] || b == cand[i]) continue;

      if(get(a, i) != get(b, i)) dsu_union(a, b, i);
      else ciclo[i] = 1;

    }
  }

  if(get(a, 4) != get(b, 4)) dsu_union(a, b, 4);
  else{
    if(ciclo_geral[get(a, 4)] == 0) cnt_ciclo ++;
    ciclo_geral[get(a, 4)] = 1;
    sz_ciclo = sz[get(a, 4)][4];
  }

  if(cnt_ciclo > 1) ok = false;

  /*cout << "after link " << a << " " << b << ", cnt_ciclo =  " << cnt_ciclo << "\n";

  for(int i=0; i<(int) cand.size(); i++){
    cout << cand[i] << " " << ciclo[i] << "\n";
  }

  cout << ".\n";
  */

}

int CountCritical(){

  // cout << "cnt_ciclo = " << cnt_ciclo << "\n";

  if(!ok) return 0;

  if(cnt_ciclo > 1) return 0;

  if(cnt_3 == 0){
    if(cnt_ciclo == 0) return n;
    return sz_ciclo;
  }

  assert((int) cand.size() <= 4);

  int ans = 0;

  for(int i=0; i<(int) cand.size(); i++) if(!ciclo[i]) ans ++;

  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...
#Verdict Execution timeMemoryGrader output
Fetching results...