제출 #1330668

#제출 시각아이디문제언어결과실행 시간메모리
1330668joacruMechanical Doll (IOI18_doll)C++20
100 / 100
188 ms20588 KiB
#include "doll.h"

#include <iostream>
#include <assert.h>
#include <algorithm>
#include <vector>

#define forn(i,n) for(int i=0;i<(int)n;++i)
#define forit(i,a,n) for(int i=a;i<=(int)n;++i)

#define DBG(a) cerr<<#a<<" = "<<(a)<<endl
#define DBGA(a) cerr<<#a<<" = "<<(a)<<", ";
#define DBG2(a,b) do{DBGA(a)DBG(b);}while(0)
#define DBG3(a,b,c) do{DBGA(a)DBGA(b)DBG(c);}while(0)

#define LINE cerr<<"===================================="<<endl

#define SZ(a) (int)a.size()
#define ALL(a) a.begin(),a.end()

using namespace std;

template<typename T>
ostream &operator<<(ostream &os, vector<T>&v){
	os<<"[";
	forn(i,SZ(v)){
		if(i) os<<", ";
		os<<v[i];
	}
	os<<"]";
	return os;
}

const int LOG=18, INF = 1000000000;

struct Graph{
	int n;
	vector<vector<int>> g;
	vector<int> e;
	vector<bool> s;
	Graph(int m){
		resize(m);
	}
	void resize(int m){
		n=m;
		g.resize(n);
		s.resize(n);
		e.resize(n);
	}
	void add(int u, int v){
		if(max(u,v)>=n) resize(max(u,v)+1);
		assert(SZ(g[u])<=2);
		g[u].push_back(v);
	}
	void complete(){
		forn(i,n) while(SZ(g[i]) < 2) add(i,-1); // lo lleva a otro lado
	}
	int simulate(vector<int> &a){
		int u = 0;
		int ret = 1; // entra aqui
		while(u != -1){
			//~ DBG(u);
			++ret;
			int v = g[u][s[u]];
			s[u] = !s[u];
			if(v == -1){
				++e[u];
				assert(e[u] <= 2);
				a.push_back(u);
			}
			u = v;
		}
		//~ DBG(s);
		//~ DBG(ret);
		//~ LINE;
		return ret;
	}
	int simulate(int x, vector<int> &a){
		int ret = 0;
		forn(_,x){
			ret += simulate(a);
			//~ DBG2(_+1,ret);
		}
		forn(i,n-1) assert(!s[i]); // el ultimo es un señuelo
		return ret;
	}
};

int node = 0;

int build(int n, Graph &g){
	if(n == 1){
		return -1;
	}
	int u = node++;
	int l = build(n/2, g), r = build(n/2, g);
	g.add(u,l);
	g.add(u,r);
	return u;
}

void create_circuit(int M, std::vector<int> A) {
	int n = SZ(A);
	vector<int> C(M+1), X, Y;
	if(n == 1){
		forit(i,1,M) C[i] = i;
		C[0] = A[0];
		C[A[0]] = 0;
		answer(C, X, Y);
		return;
	}
	Graph g(1);
	vector<int> path;
	for(int i=LOG-1;i>=0;--i){
		if((1<<i)>n){
			path.push_back(0);
			continue;
		}
		int u = node++;
		path.push_back(u);
	}
	reverse(ALL(path));
	for(int i=LOG-1;i>=0;--i){
		if((1<<i)>n) continue; // no me sirve
		int u = path[i]; // luego hay que tratarlos como negativos
		//~ DBG(u);
		if(n&(1<<i)){ // si está este nodo, crear el arbolito
			int aux = build(1<<i, g);
			g.add(u,aux);
		} else{ // no está
			g.add(u,0);
		}
		if(i) g.add(u,path[i-1]);
		else{
			X.resize(node,INF);
			Y.resize(node,INF);
			g.add(u, node++);
		}
	}
	g.complete(); // para el señuelo
	//~ DBG(g.g);
	forn(i,g.n-1){
		for(int &x: g.g[i]){
			if(x == -1) continue;
			if(x == g.n-1){
				Y[i] = 0;
				continue;
			}
			int u = i, v = -x-1;
			if(X[u] == INF) X[u] = v;
			else Y[u] = v;
		}
	}
	vector<int> ord;
	g.simulate(n+1, ord);
	ord.pop_back();
	//~ DBG2(ord, A);
	assert(SZ(ord) == SZ(A));
	forn(i,SZ(ord)){
		if(X[ord[i]]==INF) X[ord[i]] = A[i];
		else Y[ord[i]] = A[i];
	}
	forit(i,0,M) C[i] = -1;
	//~ DBG3(C,X,Y);
	answer(C, X, Y);
}

#ifdef LOCAL
#include "grader.cpp"
#endif
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...