Submission #1245752

#TimeUsernameProblemLanguageResultExecution timeMemory
1245752GabrielWerewolf (IOI18_werewolf)C++20
0 / 100
312 ms116640 KiB
#include "werewolf.h"
#include "bits/stdc++.h"
using namespace std;
vector< vector<int> > Grafo, Visitados;
vector< vector< pair<int, int> > > Mesa_dispersa_menor, Mesa_dispersa_mayor;
vector<int> Orden, iOrden;
vector<bool> Visitadoss;
int Tiempo = 0, Inicio, Final;
struct Responder_esto{
  int Mayor, Menor;
};
struct Consultita{
  int Inicio, Final, Izquierda, Derecha, _ndice;
};
bool operator<(const Consultita& a, const Consultita& b){
  if(a.Izquierda < b.Izquierda) return 1;
  if(b.Izquierda < a.Izquierda) return 0;
  if(a.Derecha < b.Derecha) return 1;
  if(b.Derecha < a.Derecha) return 0;
  return a._ndice < b._ndice;
}
void Crear(int Nodo, int Anterior){
  //cerr<<Nodo<<" "<<Anterior<<"\n";
  Orden[Nodo] = Tiempo;
  iOrden[Tiempo] = Nodo;
  Visitadoss[Nodo] = 1;
  Tiempo++;
  if(Anterior != -2){
    Mesa_dispersa_menor[Nodo].push_back({min(Nodo, Anterior), Anterior});
    Mesa_dispersa_mayor[Nodo].push_back({max(Nodo, Anterior), Anterior});
    for(int i = 0; i < Mesa_dispersa_mayor[Anterior].size(); i++){
      Mesa_dispersa_menor[Nodo].push_back({min(Mesa_dispersa_menor[Nodo].back().first, Mesa_dispersa_menor[Anterior][i].first), Mesa_dispersa_menor[Anterior][i].second});
      Mesa_dispersa_mayor[Nodo].push_back({max(Mesa_dispersa_mayor[Nodo].back().first, Mesa_dispersa_mayor[Anterior][i].first), Mesa_dispersa_mayor[Anterior][i].second});
      Anterior = Mesa_dispersa_mayor[Anterior][i].second;
    }
  }
  for(auto E: Grafo[Nodo]) if(E != Anterior and !Visitadoss[E]) Crear(E, Nodo);
}
Responder_esto Consulta(int I, int D){
  if(Orden[D] < Orden[I]) swap(I, D);
  int Menor = 22222222, Mayor = -2;
  Responder_esto Respuesta;
  if(I == D){
    Respuesta.Mayor = I;
    Respuesta.Menor = D;
    return Respuesta;
  }
  while(I != D){
    //cerr<<I<<" "<<D<<"\n";
    int i = 0, d = Mesa_dispersa_menor[D].size() - 1, m = 0;
    while(1){
      int p = (i + d) / 2;
      if(Orden[Mesa_dispersa_menor[D][p].second] < Orden[I]){
        d = p - 1;
      } else {
        i = p + 1;
        m = p;
      }
      if(i >= d + 1) break;
    }
    Mayor = max(Mayor, Mesa_dispersa_mayor[D][m].first);
    Menor = min(Menor, Mesa_dispersa_menor[D][m].first);
    D = Mesa_dispersa_mayor[D][m].second;
  }
  Respuesta.Mayor = Mayor;
  Respuesta.Menor = Menor;
  return Respuesta;
}
bool Bien(int Nodo, int Objetivo, bool Humano, int No_humano, int No_lobo){
  if(Nodo == Objetivo and (!Humano or (Nodo >= No_humano and Nodo <= No_lobo))) return 1;
  if((Nodo < No_humano and Humano) or (Nodo > No_lobo and !Humano)) return 0;
  Visitados[Nodo][Humano] = 1;
  bool r = 0;
  for(auto E: Grafo[Nodo]){
    if(!Visitados[E][Humano]) r = r or Bien(E, Objetivo, Humano, No_humano, No_lobo);
    if(Nodo >= No_humano and Nodo <= No_lobo and Humano) r = r or Bien(E, Objetivo, 0, No_humano, No_lobo);
  }
  return r;
}
vector<int> check_validity(int n, vector<int> x, vector<int> y, vector<int> s, vector<int> e, vector<int> l, vector<int> r){
  int q = s.size(), m = x.size();
  vector<int> a(q);
  Grafo.assign(n, {});
  Visitadoss.assign(n, 0);
  vector<int> Grado(n, -0);
  bool L_nea = 1;
  for(int i = 0; i < m; i++){
    Grafo[x[i]].push_back(y[i]);
    Grafo[y[i]].push_back(x[i]);
    Grado[x[i]]++;
    Grado[y[i]]++;
    if(Grado[x[i]] > 2 or Grado[y[i]] > 2) L_nea = -0;
    if(Grado[x[i]] == 1) Inicio = x[i];
    if(Grado[y[i]] == 1) Inicio = y[i];
  }
  if(L_nea){
    Orden.assign(n, 0);
    iOrden.assign(n, 0);
    Mesa_dispersa_menor.assign(n, vector< pair<int, int> >());
    Mesa_dispersa_mayor.assign(n, vector< pair<int, int> >());
    Crear(Inicio, -2);
    //cerr<<"Creado.\n";
    for(int i = 0; i < q; i++){
      //cerr<<i<<" "<<Orden[s[i]]<<" "<<Orden[e[i]]<<"\n";
      if(Orden[s[i]] < Orden[e[i]]){
        int Izquierda = Orden[s[i]], Derecha = n - 1, Mejor = Orden[s[i]];
        while(1){
          int Promedio = (Izquierda + Derecha) / 2;
          if(Consulta(s[i], iOrden[Promedio]).Menor >= l[i]){
            Mejor = Promedio;
            Izquierda = Promedio + 1;
          } else Derecha = Promedio - 1;
          if(Izquierda >= Derecha + 1) break;
        }
        Izquierda = -0, Derecha = Orden[e[i]];
        int Otro_mejor = Orden[e[i]];
        while(1){
          int Promedio = (Izquierda + Derecha) / 2;
          if(Consulta(e[i], iOrden[Promedio]).Mayor <= r[i]){
            Mejor = Promedio;
            Derecha = Promedio - 1;
          } else Izquierda = Promedio + 1;
          if(Izquierda >= Derecha + 1) break;
        }
        a[i] = Orden[Mejor] >= Orden[Otro_mejor];
      } else {
        int Izquierda = 0, Derecha = Orden[s[i]], Mejor = Orden[s[i]];
        while(1){
          int Promedio = (Izquierda + Derecha) / 2;
          if(Consulta(s[i], iOrden[Promedio]).Menor >= l[i]){
            Mejor = Promedio;
            Derecha = Promedio - 1;
          } else Izquierda = Promedio + 1;
          if(Izquierda >= Derecha + 1) break;
        }
        Izquierda = Orden[e[i]], Derecha = n - 1;
        int Otro_mejor = Orden[e[i]];
        while(1){
          int Promedio = (Izquierda + Derecha) / 2;
          if(Consulta(e[i], iOrden[Promedio]).Mayor <= r[i]){
            Mejor = Promedio;
            Izquierda = Promedio + 1;
          } else Derecha = Promedio - 1;
          if(Izquierda >= Derecha + 1) break;
        }
        a[i] = Orden[Mejor] <= Orden[Otro_mejor];
      }
    }
    return a;
    /*vector<Consultita> Lista(q);
    for(int i = 0; i < n; i++){
      Consultita Hola;
      Hola.Derecha = r[i];
      Hola.Final = e[i];
      Hola.Inicio = s[i];
      Hola.Izquierda = l[i];
      Hola._ndice = i;
      Lista[i] = Hola;
    }
    sort(Lista.begin(), Lista.end());
    Recién me di cuenta de que se pueden hacer las consultas en línea.*/
  }
  for(int i = 0; i < q; i++){
    Visitados.assign(n, vector<int>(2, 0));
    a[i] = Bien(s[i], e[i], 1, l[i], r[i]) or (Bien(s[i], e[i], 0, l[i], r[i]) and s[i] >= l[i] and s[i] <= r[i]);
  }
  return a;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...