Created
August 23, 2018 14:15
-
-
Save IvanIsCoding/79fa951989731f161542868c8c51cc7f to your computer and use it in GitHub Desktop.
Japanese Olympiad in Informatics Spring Camp 2018
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Ivan Carvalho | |
// Library - JOI SC 2018 | |
// O(N*log(N)) | |
#include <cstdio> | |
#include <vector> | |
#include "library.h" | |
using namespace std; | |
const int MAXN = 1001; | |
static int pai[MAXN],v1[MAXN],v2[MAXN],N; | |
static vector<int> grafo[MAXN],temporario[MAXN],filhos[MAXN],M; | |
static void addEdge(int a,int b){ | |
grafo[a].push_back(b); | |
grafo[b].push_back(a); | |
} | |
static int isAdj(int a,int b){ | |
M.clear(); | |
M.assign(N,0); | |
M[a-1] = 1; | |
M[b-1] = 1; | |
int ans = Query(M); | |
return (ans == 1); | |
} | |
static int find(int x){ | |
if(x == pai[x]) return x; | |
return pai[x] = find(pai[x]); | |
} | |
static void join_case1(int x,int i){ | |
pai[i] = x; | |
if(isAdj(v1[x],i)){ | |
addEdge(v1[x],i); | |
v1[x] = i; | |
} | |
else{ | |
addEdge(v2[x],i); | |
v2[x] = i; | |
} | |
filhos[x].push_back(i); | |
} | |
static void join_case2(int x,int y,int i){ | |
if(x > y) swap(x,y); | |
int adj_v1x = isAdj(v1[x],i); | |
int adj_v2x = 1 - adj_v1x; | |
int adj_v1y = isAdj(v1[y],i); | |
int adj_v2y = 1 - adj_v1y; | |
if(adj_v1x) addEdge(v1[x],i); | |
else addEdge(v2[x],i); | |
if(adj_v1y) addEdge(v1[y],i); | |
else addEdge(v2[y],i); | |
if(adj_v1x == 1 && adj_v1y == 1){ | |
v1[x] = v2[y]; | |
} | |
else if(adj_v1x == 1 && adj_v1y == 0){ | |
v1[x] = v1[y]; | |
} | |
else if(adj_v1x == 0 && adj_v1y == 1){ | |
v2[x] = v2[y]; | |
} | |
else{ | |
v2[x] = v1[y]; | |
} | |
pai[y] = x; | |
pai[i] = x; | |
filhos[x].push_back(i); | |
for(int j : filhos[y]) filhos[x].push_back(j); | |
filhos[y].clear();; | |
} | |
static void create(int i){ | |
pai[i] = i; | |
v1[i] = i; | |
v2[i] = i; | |
filhos[i].push_back(i); | |
} | |
static int doQuery(int i,vector<int>& V){ | |
M.clear(); | |
M.assign(N,0); | |
M[i-1] = 1; | |
for(int j : V){ | |
for(int k : filhos[j]){ | |
M[k-1] = 1; | |
} | |
} | |
return Query(M); | |
} | |
static void divide_and_conquer(int i, vector<int>& V, int caso ){ | |
if(caso == 0) return; | |
if(V.size() == 1){ | |
temporario[i].push_back(V[0]); | |
return; | |
} | |
int mid = V.size()/2; | |
vector<int> firstHalf,lastHalf; | |
for(int j = 0;j<V.size();j++){ | |
if(j < mid) firstHalf.push_back(V[j]); | |
else lastHalf.push_back(V[j]); | |
} | |
int qtd = doQuery(i,firstHalf); | |
if(caso == 1){ | |
if(qtd == firstHalf.size()){ | |
lastHalf.clear(); | |
divide_and_conquer(i,firstHalf,1); | |
} | |
else{ | |
firstHalf.clear(); | |
divide_and_conquer(i,lastHalf,1); | |
} | |
} | |
else if(caso == 2){ | |
if(qtd == firstHalf.size()){ | |
divide_and_conquer(i,firstHalf,1); | |
divide_and_conquer(i,lastHalf,1); | |
} | |
else if(qtd == firstHalf.size() - 1){ | |
lastHalf.clear(); | |
divide_and_conquer(i,firstHalf,2); | |
} | |
else{ | |
firstHalf.clear(); | |
divide_and_conquer(i,lastHalf,2); | |
} | |
} | |
} | |
void Solve(int n){ | |
N = n; | |
vector<int> M(N); | |
create(1); | |
for(int i = 2;i<=N;i++){ | |
vector<int> V; | |
for(int j = 1;j<i;j++) if(find(j) == j) V.push_back(j); | |
int qtd = doQuery(i,V); | |
if(qtd == V.size() + 1){ | |
create(i); | |
continue; | |
} | |
else if(qtd == V.size()){ | |
divide_and_conquer(i, V, 1); | |
join_case1(temporario[i][0], i ); | |
} | |
else{ | |
divide_and_conquer(i, V, 2); | |
join_case2(temporario[i][0], temporario[i][1], i ); | |
} | |
} | |
int last = -1; | |
vector<int> resposta; | |
for(int i = 1;i<=N;i++){ | |
if(grafo[i].size() <= 1){ | |
resposta.push_back(i); | |
break; | |
} | |
} | |
while(resposta.size() != N){ | |
int x = resposta.back(); | |
if(grafo[x][0] != last){ | |
resposta.push_back(grafo[x][0]); | |
} | |
else{ | |
resposta.push_back(grafo[x][1]); | |
} | |
last = x; | |
} | |
Answer(resposta); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment