Submission #544502

#TimeUsernameProblemLanguageResultExecution timeMemory
544502model_codeFlights (JOI22_flights)C++17
95 / 100
2083 ms6944 KiB
#include "Ali.h"
#include <iostream>
#include <map>
#include <stack>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

namespace {
	
	const int LIMIT1 = 7;
	const int LIMIT2 = 13;
	const int BACKET = 4;
	const int TREEWAY = 66;
	
	// Memo
	int Scenario = 0;
	int MainRoot = 0;
	int Cnt = 0, Rank;
	int cl[20029], CntP;
	int ID[20029];
	vector<int> tmp;
	string str_tmp = "";
	
	// Graph
	int N, U[20029], V[20029];
	int dist[20029];
	int Par[20029];
	vector<int> G[20029];
	vector<int> Gc[20029];
	
	// Group Division
	int groupcnt = 0;
	int group[20029];      // Group ID
	int groupnum[20029];   // Vertex ID in group
	int dp[20029];
	vector<int> S[20029];  // Connect or Cut
	vector<int> Gr[20029]; // Group Division
	
	// Tree Parentheses
	map<string, int> Map;
	vector<string> Tree;
	
	void AllInit() {
		Cnt = 0; Rank = 0;
		groupcnt = 0; MainRoot = -1; str_tmp = "";
		tmp.clear();
		for (int i = 0; i < 20029; i++) {
			cl[i] = 0; ID[i] = 0;
			U[i] = 0; V[i] = 0; G[i].clear();
			dist[i] = 0; Par[i] = 0;
			group[i] = 0; groupnum[i] = 0; dp[i] = 0;
			S[i].clear(); Gr[i].clear();
		}
	}
	
	pair<string, bool> dfs_check(int pos) {
		vector<string> Vlist;
		string Vreturn = "0";
		bool CurrentState = true;
		dp[pos] = 1;
		for (int to : Gc[pos]) {
			pair<string, bool> ret = dfs_check(to);
			Vlist.push_back(ret.first);
			Vreturn += ret.first;
			dp[pos] += dp[to];
			if (ret.second == false) CurrentState = false;
		}
		for (int i = 0; i < (int)Vlist.size() - 1; i++) {
			if (Vlist[i] > Vlist[i + 1]) CurrentState = false;
		}
		Vreturn += "1";
		return make_pair(Vreturn, CurrentState);
	}
	
	bool hantei(string ss) {
		for (int i = 0; i < (int)ss.size() / 2 + 1; i++) Gc[i].clear();
		for (int i = 0; i < (int)ss.size() / 2 + 1; i++) dp[i] = 0;
		stack<int> ST;
		int num = 1; ST.push(0);
		for (int i = 0; i < (int)ss.size(); i++) {
			if (ss[i] == '0') {
				int u1 = ST.top(), u2 = num;
				ST.push(u2);
				Gc[u1].push_back(u2);
				num += 1;
			}
			if (ss[i] == '1') {
				ST.pop();
			}
		}
		
		// Subtree Size Check
		pair<string, bool> u = dfs_check(0);
		for (int i = 1; i < num; i++) {
			if (dp[i] >= 7) return false;
		}
		for (int i = 0; i < num; i++) {
			if (Gc[i].size() >= 3) return false;
		}
		if (u.second == false) return false;
		return true;
	}
	
	void dfs_init(int pos, int dep, string ss) {
		if (dep == 0 && pos == (LIMIT2 - 1) * 2 && hantei(ss) == true) {
			int idx = Tree.size();
			Map[ss] = idx;
			Tree.push_back(ss);
		}
		if (pos >= (LIMIT2 - 1) * 2 || dep > (LIMIT2 - 1) * 2 - pos) {
			return;
		}
		string s1 = ss + "0";
		string s2 = ss + "1";
		dfs_init(pos + 1, dep + 1, s1);
		if (dep >= 1) dfs_init(pos + 1, dep - 1, s2);
	}
	
	void init() {
		dfs_init(0, 0, "");
	}
};

int ToNumber(string ss) {
	int cur = 0;
	for (int i = 0; i < (int)ss.size(); i++) {
		if (ss[i] == '1') cur += (1 << i);
	}
	return cur;
}

string ToString(long long val, int len) {
	string ss = "";
	for (int i = 0; i < len; i++) {
		if ((val & (1LL << i)) == 0) ss += "0";
		if ((val & (1LL << i)) != 0) ss += "1";
	}
	return ss;
}

void dfs1(int pos, int par) {
	dp[pos] = 1;
	Par[pos] = par;
	for (int to : G[pos]) {
		if (to == par) continue;
		dfs1(to, pos);
		if (dp[to] < LIMIT1) {
			S[pos].push_back(to);
			S[to].push_back(pos);
			dp[pos] += dp[to];
		}
		else {
			tmp.push_back(to);
		}
	}
}

string dfs2_1(int pos, int par) {
	vector<pair<string, int>> Vlist;
	for (int to : S[pos]) {
		if (to == par) continue;
		string u = dfs2_1(to, pos);
		Vlist.push_back(make_pair(u, to));
	}
	
	// Rearrange S[pos]
	sort(Vlist.begin(), Vlist.end());
	S[pos].clear();
	string Vreturn = "0";
	for (int i = 0; i < (int)Vlist.size(); i++) {
		S[pos].push_back(Vlist[i].second);
		Vreturn += Vlist[i].first;
	}
	if (par != -1) S[pos].push_back(par);
	
	// Return
	Vreturn += "1";
	return Vreturn;
}

void dfs2_2(int pos, int par) {
	group[pos] = groupcnt;
	groupnum[pos] = (int)Gr[groupcnt].size();
	Gr[groupcnt].push_back(pos);
	
	// Recursion
	for (int to : S[pos]) {
		if (to == par) continue;
		dfs2_2(to, pos);
	}
}

void dfs3(int pos, int dep) {
	dist[pos] = dep;
	for (int to : G[pos]) {
		if (dist[to] != -1) continue;
		dfs3(to, dep + 1);
	}
}

void dfs5(int pos, int par) {
	cl[pos] = CntP;
	CntP += 1;
	for (int to : S[pos]) {
		if (to == par) continue;
		str_tmp += "0";
		dfs5(to, pos);
		str_tmp += "1";
	}
}

void Init(int n, vector<int> u, vector<int> v) {
	AllInit();
	if (Scenario == 0) init();
	Scenario += 1;
	
	// Initialize
	N = n;
	for (int i = 0; i < N - 1; i++) {
		U[i] = u[i];
		V[i] = v[i];
		G[U[i]].push_back(V[i]);
		G[V[i]].push_back(U[i]);
	}
	
	// Get Root
	for (int i = 0; i < N; i++) {
		if (G[i].size() == 1) { MainRoot = i; break; }
	}
	
	// Group Division [Part 1]
	for (int i = 0; i < N; i++) dp[i] = 0;
	tmp.push_back(MainRoot);
	dfs1(MainRoot, -1);
	
	// Add Vertices to 13
	int NumVertices = N;
	for (int root : tmp) {
		for (int seco : S[root]) {
			int cx = seco, par = root;
			while (true) {
				int nex = -1;
				for (int to : S[cx]) { if (to != par) nex = to; }
				if (nex == -1) break;
				par = cx; cx = nex;
			}
			int Last = cx;
			for (int k = 0; k < 6 - dp[seco]; k++) {
				S[Last].push_back(NumVertices);
				S[NumVertices].push_back(Last);
				G[Last].push_back(NumVertices);
				G[NumVertices].push_back(Last);
				//cout << "root = " << root << ", Edge = (" << Last << ", " << NumVertices << ")" << endl;
				Last = NumVertices;
				NumVertices += 1;
			}
		}
		for (int j = 0; j < 2 - (int)S[root].size(); j++) {
			int Last = root;
			for (int k = 0; k < 6; k++) {
				S[Last].push_back(NumVertices);
				S[NumVertices].push_back(Last);
				G[Last].push_back(NumVertices);
				G[NumVertices].push_back(Last);
				//cout << "root = " << root << ", Edge = (" << Last << ", " << NumVertices << ")" << endl;
				Last = NumVertices;
				NumVertices += 1;
			}
		}
	}
	
	// Get Distance
	for (int i = 0; i < NumVertices; i++) dist[i] = -1;
	dfs3(MainRoot, 0);
	vector<pair<int, int>> DistSort;
	for (int i = 0; i < NumVertices; i++) DistSort.push_back(make_pair(dist[i], i));
	sort(DistSort.begin(), DistSort.end());
	
	// Group Division [Part 2]
	for (int i = 0; i < NumVertices; i++) group[i] = -1;
	for (int i = 0; i < NumVertices; i++) {
		int idx = DistSort[i].second;
		if (group[idx] != -1) continue;
		dfs2_1(idx, -1);
		dfs2_2(idx, -1);
		groupcnt += 1;
	}
	
	// Set ID
	for (int i = 0; i < groupcnt; i++) {
		CntP = 0;
		dfs5(Gr[i][0], -1);
		for (int j = 0; j < (int)Gr[i].size(); j++) {
			if (Gr[i][j] >= N) continue;
			ID[Gr[i][j]] = LIMIT2 * i + cl[Gr[i][j]];
			SetID(Gr[i][j], ID[Gr[i][j]]);
		}
	}
}

string SendA(string S) {
	// Get Group Number
	int GX = 0, GY = 0;
	Rank = ToNumber(S);
	for (int i = 0; i < 1430; i++) {
		for (int j = i; j < 1430; j++) {
			if (Cnt == Rank) { GX = i; GY = j; }
			Cnt += 1;
		}
	}
	
	// Get String When GX == GY
	if (GX == GY) {
		str_tmp = "";
		dfs5(Gr[GX][0], -1);
		int num_Tree = Map[str_tmp];
		return ToString(num_Tree, 10);
	}
	
	// Get String When GX != GY
	if (GX != GY) {
		string str = "";
		
		// Get GX-GY Path
		int pos = Gr[GY][0];
		while (pos != -1 && group[pos] != GX) {
			pos = Par[pos];
		}
		
		// Get "Representative" Vertex in Group
		int u1 = Gr[GX][0]; if (pos != -1) u1 = pos;
		int u2 = Gr[GY][0];
		
		// Send Tree of GX
		str_tmp = "";
		dfs5(Gr[GX][0], -1);
		long long num_GX = Map[str_tmp]; //cout << str_tmp << " " << Map[str_tmp] << endl;
		
		// Send Tree of GY
		str_tmp = "";
		dfs5(Gr[GY][0], -1);
		long long num_GY = Map[str_tmp];
		long long rep_GX = ID[u1] % LIMIT2; //cout << str_tmp << " " << Map[str_tmp] << endl;
		
		// Get Distance between u1 and u2
		for (int i = 0; i < N; i++) dist[i] = -1;
		dfs3(u1, 0);
		long long dst_path = dist[u2];
		
		// Get String & Return
		long long FinalVal = 0;
		FinalVal += 1LL * num_GX;
		FinalVal += 1LL * num_GY * TREEWAY;
		FinalVal += 1LL * rep_GX * TREEWAY * TREEWAY;
		FinalVal += 1LL * dst_path * TREEWAY * TREEWAY * LIMIT2;
		for (int i = 1; i <= 30; i++) {
			if (FinalVal < (1LL << i)) return ToString(FinalVal, i);
			else FinalVal -= (1LL << i);
		}
	}
}
#include "Benjamin.h"
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
using namespace std;

namespace {
	
	const int LIMIT2 = 13;
	const int BACKET = 4;
	const int TREEWAY = 66;
	
	// Group
	int Scenario = 0;
	int N, X, Y;
	int Cnt = 0, Rank;
	int GroupX, NumX;
	int GroupY, NumY;
	
	// Graph
	vector<int> G[20029];
	vector<int> Gc[20029];
	int dist[20029], CntS;
	int dp[20029];
	
	// Tree Parentheses
	map<string, int> Map;
	vector<string> Tree;
	
	void AllInit() {
		Cnt = 0; Rank = 0; CntS = 0;
		for (int i = 0; i < 20029; i++) {
			G[i].clear(); dist[i] = 0;
		}
	}
	
	pair<string, bool> dfs_check(int pos) {
		vector<string> Vlist;
		string Vreturn = "0";
		bool CurrentState = true;
		dp[pos] = 1;
		for (int to : Gc[pos]) {
			pair<string, bool> ret = dfs_check(to);
			Vlist.push_back(ret.first);
			Vreturn += ret.first;
			dp[pos] += dp[to];
			if (ret.second == false) CurrentState = false;
		}
		for (int i = 0; i < (int)Vlist.size() - 1; i++) {
			if (Vlist[i] > Vlist[i + 1]) CurrentState = false;
		}
		Vreturn += "1";
		return make_pair(Vreturn, CurrentState);
	}
	
	bool hantei(string ss) {
		for (int i = 0; i < (int)ss.size() / 2 + 1; i++) Gc[i].clear();
		for (int i = 0; i < (int)ss.size() / 2 + 1; i++) dp[i] = 0;
		stack<int> ST;
		int num = 1; ST.push(0);
		for (int i = 0; i < (int)ss.size(); i++) {
			if (ss[i] == '0') {
				int u1 = ST.top(), u2 = num;
				ST.push(u2);
				Gc[u1].push_back(u2);
				num += 1;
			}
			if (ss[i] == '1') {
				ST.pop();
			}
		}
		
		// Subtree Size Check
		pair<string, bool> u = dfs_check(0);
		for (int i = 1; i < num; i++) {
			if (dp[i] >= 7) return false;
		}
		for (int i = 0; i < num; i++) {
			if (Gc[i].size() >= 3) return false;
		}
		if (u.second == false) return false;
		return true;
	}
	
	void dfs_init(int pos, int dep, string ss) {
		if (dep == 0 && pos == (LIMIT2 - 1) * 2 && hantei(ss) == true) {
			int idx = Tree.size();
			Map[ss] = idx;
			Tree.push_back(ss);
		}
		if (pos >= (LIMIT2 - 1) * 2 || dep > (LIMIT2 - 1) * 2 - pos) {
			return;
		}
		string s1 = ss + "0";
		string s2 = ss + "1";
		dfs_init(pos + 1, dep + 1, s1);
		if (dep >= 1) dfs_init(pos + 1, dep - 1, s2);
	}
	
	void init() {
		dfs_init(0, 0, "");
	}
};

long long ToNumber2(string ss) {
	long long cur = 0;
	for (int i = 0; i < (int)ss.size(); i++) {
		if (ss[i] == '1') cur += (1LL << i);
	}
	return cur;
}

string ToString2(int val, int len) {
	string ss = "";
	for (int i = 0; i < len; i++) {
		if ((val & (1 << i)) == 0) ss += "0";
		if ((val & (1 << i)) != 0) ss += "1";
	}
	return ss;
}

void MakeGraph(string V) {
	stack<int> Stack;
	for (int i = 0; i < (int)V.size(); i++) G[i].clear();
	CntS = 1; Stack.push(0);
	for (int i = 0; i < (int)V.size(); i++) {
		if (V[i] == '0') {
			int u1 = Stack.top(), u2 = CntS;
			CntS += 1;
			Stack.push(u2);
			G[u1].push_back(u2);
			G[u2].push_back(u1);
		}
		else {
			if (Stack.size() == 0) break;
			Stack.pop();
		}
	}
}

void dfs4(int pos, int dep) {
	dist[pos] = dep;
	for (int to : G[pos]) {
		if (dist[to] != -1) continue;
		dfs4(to, dep + 1);
	}
}

int GetDist(int u1, int u2) {
	for (int i = 0; i < 20020; i++) dist[i] = -1;
	dfs4(u1, 0);
	return dist[u2];
}

string SendB(int n, int x, int y) {
	AllInit();
	if (Scenario == 0) init();
	Scenario += 1;
	
	N = n; X = x; Y = y;
	if (X > Y) swap(X, Y);
	GroupX = X / LIMIT2; NumX = X % LIMIT2;
	GroupY = Y / LIMIT2; NumY = Y % LIMIT2;
	
	// Get Rank
	for (int i = 0; i < 1430; i++) {
		for (int j = i; j < 1430; j++) {
			if (i == GroupX && j == GroupY) Rank = Cnt;
			Cnt += 1;
		}
	}
	
	// Send Email
	return ToString2(Rank, 20);
}

int Answer(string T) {
	// If the group is same
	if (GroupX == GroupY) {
		string Tree1 = Tree[ToNumber2(T)];
		MakeGraph(Tree1);
		return GetDist(NumX, NumY);
	}
	
	// If the group is not same
	if (GroupX != GroupY) {
		long long RecieveVal = ToNumber2(T);
		for (int i = 1; i < T.size(); i++) RecieveVal += (1LL << i);
		int TreeV1 = RecieveVal % TREEWAY;
		int TreeV2 = (RecieveVal / (TREEWAY)) % TREEWAY;
		int VertX = (RecieveVal / (TREEWAY * TREEWAY)) % LIMIT2;
		int d3 = (RecieveVal / (TREEWAY * TREEWAY * LIMIT2));
		
		// Get d1, d2
		int d1 = 0, d2 = 0;
		string Tree1 = Tree[TreeV1];
		string Tree2 = Tree[TreeV2];
		MakeGraph(Tree1); d1 = GetDist(VertX, NumX);
		MakeGraph(Tree2); d2 = GetDist(0, NumY);
		
		// Return
		return d1 + d2 + d3;
	}
}

Compilation message (stderr)

Ali.cpp: In function 'std::string SendA(std::string)':
Ali.cpp:363:1: warning: control reaches end of non-void function [-Wreturn-type]
  363 | }
      | ^
grader_ali.cpp:10:8: warning: '{anonymous}::_randmem' defined but not used [-Wunused-variable]
   10 |   char _randmem[12379];
      |        ^~~~~~~~

Benjamin.cpp: In function 'int Answer(std::string)':
Benjamin.cpp:191:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::__cxx11::basic_string<char>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  191 |   for (int i = 1; i < T.size(); i++) RecieveVal += (1LL << i);
      |                   ~~^~~~~~~~~~
Benjamin.cpp:207:1: warning: control reaches end of non-void function [-Wreturn-type]
  207 | }
      | ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...