Submission #250397

#TimeUsernameProblemLanguageResultExecution timeMemory
250397ernestvwMechanical Doll (IOI18_doll)C++11
85.55 / 100
175 ms19576 KiB
#include <bits/stdc++.h>
using namespace std;

#define sz(x) ((int)x.size())

void answer(vector<int> C, vector<int> X, vector<int> Y);

const int K = 1000*1000;

int n, m;
vector<int> a;
vector<vector<int>> adj;

int p = 0;
vector<int> c, x, y;

int new_switch(int g, int d) {
	p++;
	x.push_back(g);
	y.push_back(d);
	return -p;
}

int new_switch(int g) {
	p++;
	x.push_back(-p);
	y.push_back(g);
	return -p;
}

struct node {
	int g, d, st, val;
};

vector<node> tree;

int newNode(int a = 0, int b = 0) {
	tree.push_back({a, b, 0, -1});
	return sz(tree)-1;
}

int buildTree(int t) {
	if(sz(adj[t]) == 2)
		return newNode(-2, -2);
	vector<int> nodes;
	int pr = 1;
	while(pr < sz(adj[t])) pr *= 2;
	for(int i = 0; i < pr / 4; ++i) nodes.push_back(newNode(-2, -2));
	vector<int> sh;
	for(int i = 0; i < sz(adj[t])/2-pr/4; ++i)
		sh.push_back(newNode(-2, -2));
	if(sz(adj[t])%2 == 1) sh.push_back(newNode(-K-K, -2));
	while(sz(sh) < pr / 4) sh.push_back(newNode(-K-K, -K-K));
	reverse(sh.begin(), sh.end());
	for(auto i : sh) nodes.push_back(i);
	if(sz(adj[t]) % 2 == 1)
		tree[nodes.back()].d = -2;
	vector<int> oldNodes;
	while(sz(nodes) > 1) {
		oldNodes = nodes;
		nodes.clear();
		for(int i = 0; i < sz(oldNodes); i += 2) {
			int u = oldNodes[i], v = oldNodes[i + 1];
			if(tree[v].g == -K-K && tree[v].d == -K-K) {
				nodes.push_back(v);
				continue;
			}
			if(tree[u].g == -K-K && tree[u].d == -K-K) {
				nodes.push_back(newNode(-K-K, v));
				continue;
			}
			nodes.push_back(newNode(u, v));
		}
	}
	return nodes[0];

}

void printTree(int u) {
	if(u < 0) {
//		cout << u;
		if(u == -K-K) cout << -1;
		// u=-3-x, -u=3+x, x=-u-3
		else cout << -u-K;
		return;
	}
	cout << "(";
	printTree(tree[u].g);
	cout << ")";
	cout << u;
	cout << "(";
	printTree(tree[u].d);
	cout << ")";
}

int Cnt = 0;
int Root = 0;

void parcourir(int u, int t) {
	if(Cnt == sz(adj[t])) return;
	if(tree[u].st == 0) {
		tree[u].st = 1;
		if(tree[u].g < 0) {
			if(tree[u].g != -K-K)
				tree[u].g = -K-adj[t][Cnt++];
			parcourir(Root, t);
		}
		else parcourir(tree[u].g, t);
	}
	else {
		tree[u].st = 0;
		if(tree[u].d < 0) {
			if(tree[u].d != -K-K)
				tree[u].d = -K-adj[t][Cnt++];
			parcourir(Root, t);
		}
		else parcourir(tree[u].d, t);
	}
}

int MOM = -1;

int construire(int u) {
	if(u < 0) {
		if(u == -K-K) return MOM;
		if(u > -K) return u;
		return -K-u;
	}
	if(u == Root) {
		MOM = new_switch(0, 0);
		int g = construire(tree[u].g);
		int d = construire(tree[u].d);
		x[-MOM-1] = g;
		y[-MOM-1] = d;
		return MOM;
	}
	int g = construire(tree[u].g);
	int d = construire(tree[u].d);
	return new_switch(g, d);
}

int create(int t) {
	if(sz(adj[t]) == 0) return 0;
	if(sz(adj[t]) == 1) return adj[t][0];
	int root = buildTree(t);

//	printTree(root);
//	cout << endl;

	Cnt = 0;
	Root = root;

	parcourir(root, t);

//	printTree(root);
//	cout << endl;

	return construire(root);
}

vector<int> liste;
int PR = 1;
int mom = -1;

int build(int X, int pr) {
	if(pr == 1) {
		mom = new_switch(0, 0);
		int g = build(X, 2 * pr);
		int d = build(X + pr, 2 * pr);
		x[-mom-1] = g;
		y[-mom-1] = d;
		return mom;
	}
	if(pr == PR) return (liste[X] == -1 ? mom : liste[X]);
	int g = build(X, 2 * pr);
	int d = build(X + pr, 2 * pr);
	return new_switch(g, d);
}

int Create(int t) {
	if(sz(adj[t]) == 0) return 0;
	if(sz(adj[t]) == 1) return adj[t][0];
	int pr = 1;
	while(pr < sz(adj[t])) pr *= 2;
	PR = pr;
	liste.assign(pr, -1);
	for(int i = 0; i < pr - sz(adj[t]); ++i)
		liste[i] = -1;
	for(int i = pr - sz(adj[t]); i < pr; ++i)
		liste[i] = adj[t][i - pr + sz(adj[t])];
	return build(0, 1);
}

void create_circuit(int M, vector<int> A) {
	n = (int)A.size();
	m = M;
	a = A;

	c.assign(m + 1, 0);

	adj.assign(m + 1, vector<int>());
	for(int i = 0; i < n - 1; ++i)
		adj[a[i]].push_back(a[i + 1]);
	adj[0].push_back(a[0]);
	adj[a.back()].push_back(0);
	
	for(int i = 0; i <= m; ++i)
		c[i] = create(i);
	
	answer(c, x, y);
}
#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...