제출 #983472

#제출 시각아이디문제언어결과실행 시간메모리
983472CSQ31즐거운 행로 (APIO20_fun)C++17
100 / 100
233 ms29652 KiB
#include "fun.h"
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define sz(a) (int)(a.size())
#define fi first
#define se second
typedef long long int ll;
typedef pair<int,int> pii;
//1)root at 0
//2)find centroid, centroid is the node with smallest subtree size that is also >= n/2
const int MAXN = 111111;
int dist[4][MAXN];
vector<int> createFunTour(int n, int q) {
	if(n==2)return {0,1};
	//hoursRequired(0, N - 1);
	//attractionsBehind(0, N - 1);
	//extract centroid
	vector<int>sub(n,0);
	sub[0] = n;
	int cen = 0;
	for(int i=1;i<n;i++){
		sub[i] = attractionsBehind(0,i);
		if(2*sub[i] >= n && sub[i] < sub[cen])cen = i;
	}

	//extract children
	vector<int>ch;
	vector<int>subtree[3];
	for(int i=0;i<n;i++){
		if(i==cen)continue;
		dist[3][i] = hoursRequired(cen,i);
		if(dist[3][i] == 1)ch.pb(i);
	}

	assert(sz(ch)>=2 && sz(ch)<=3);
	//get children subtrees
	vector<bool>vis(n,0);
	vis[cen] = 1;
	for(int i=0;i<2;i++){
		for(int v=0;v<n;v++){
			if(v==cen)continue;
			dist[i][v] = hoursRequired(ch[i],v);
			if(dist[3][v] == dist[i][v] + 1){
				subtree[i].pb(v);
				vis[v] = 1;
			}
		}
	}
	for(int v=0;v<n;v++){
		if(!vis[v])subtree[2].pb(v);
	}

	set<pii,greater<pii>>s[3];
	for(int x:subtree[0])s[0].insert({dist[3][x],x});
	for(int x:subtree[1])s[1].insert({dist[3][x],x});
	for(int x:subtree[2])s[2].insert({dist[3][x],x});

	vector<int>ans;
	function<bool(int)>check = [&](int i){ //check if j and k can be merged tgt
		int j = (i+1)%3;
		int k = (j+1)%3;
		return sz(s[i]) == sz(s[j]) +  sz(s[k]);
	};
	function<void(int)>merge = [&](int i){ //merge j and k
		//merge j and k into one
		int j = (i+1)%3;
		int k = (j+1)%3;
		set<pii,greater<pii>>tmp = s[j];
		for(auto x : s[k])tmp.insert(x);
		s[0] = s[i];
		s[1] = tmp;
		s[2].clear();
	};
	vector<int>debug;
	function<void(int)>add = [&](int i){
		ans.pb(s[i].begin()->se);
		debug.pb(s[i].begin()->fi);
		s[i].erase(s[i].begin());
	};
	//cout<<sz(s[0])<<" "<<sz(s[1])<<" "<<sz(s[2])<<'\n';
	/*
	cout<<cen<<'\n';
	for(int x:ch)cout<<x<<" ";
	cout<<'\n';
	cout<<"s0"<<'\n';
	for(auto x:s[0])cout<<x.fi<<" ";
	cout<<'\n';
	cout<<"s1"<<'\n';
	for(auto x:s[1])cout<<x.fi<<" ";
	cout<<'\n';
	cout<<"s2"<<'\n';
	for(auto x:s[2])cout<<x.fi<<" ";
	cout<<'\n';
	*/



	if(!s[2].empty()){ 
		if(sz(s[0]) >= sz(s[1]) + sz(s[2])){
			merge(0);
			goto jump;
		}
		else if(sz(s[1]) >= sz(s[0]) + sz(s[2])){
			merge(1);
			goto jump;

		}
		else if(sz(s[2]) >= sz(s[0]) + sz(s[1])){
			merge(2);
			goto jump;
		}

		int i = 0;
		if(s[1].begin()->fi > s[i].begin()->fi)i = 1;
		if(s[2].begin()->fi > s[i].begin()->fi)i = 2;

		//reduce to two sub if possible
		while(true){
			assert(sz(s[0]) < sz(s[1]) + sz(s[2]));
			assert(sz(s[1]) < sz(s[0]) + sz(s[2]));
			assert(sz(s[2]) < sz(s[0]) + sz(s[1]));
			add(i);
			int j = (i+1)%3;
			int k = (j+1)%3;
			if(check(j)){
				//cout<<sz(s[0])<<" "<<sz(s[1])<<" "<<sz(s[2])<<'\n';
				if(!s[k].empty() && s[k].begin()->fi > debug.back())add(k);
				merge(j);
				goto jump;
			}
			if(check(k)){
				//cout<<i<<" "<<j<<" "<<k<<'\n';
				//cout<<s[i].begin()->fi<<" "<<s[j].begin()->fi<<" "<<s[k].begin()->fi<<'\n';
				//cout<<sz(s[0])<<" "<<sz(s[1])<<" "<<sz(s[2])<<'\n';
				if(!s[j].empty() && s[j].begin()->fi > debug.back())add(j);
				merge(k);
				goto jump;
			}
			assert(!s[j].empty() && !s[k].empty());
			i = j;
			if(s[j].begin()->fi < s[k].begin()->fi)i = k;
		}
	}
	jump:
	int cur = 0;
	while(!s[cur].empty()){
		//cout<<cur<<" "<<s[cur].begin()->fi<<'\n';
		add(cur);
		cur^=1;
	}
	cur^=1;
	assert(sz(s[cur]) <= 1);
	while(!s[cur].empty())add(cur);
	ans.pb(cen);

	// for(int i=0;i+1<n;i++){
	// 	cout<<debug[i]<<'\n';
	// 	if(i && debug[i-1] + debug[i] < debug[i] + debug[i+1]){
	// 		cout<<debug[i+1]<<'\n';
	// 		break;
	// 	}

	// }
	return ans;
}
#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...