제출 #396018

#제출 시각아이디문제언어결과실행 시간메모리
396018juggernautFun Tour (APIO20_fun)C++14
100 / 100
324 ms25860 KiB
#include "fun.h"
#include<bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
typedef pair<int,int> pi;
typedef vector<pi> vpi;
#define pb emplace_back
#define mp make_pair
#define f first
#define s second
#define ALL(x) x.begin(),x.end()
#define SZ(x) (int)x.size()
const int MAXN= 100100;

vi res;
vpi V[MAXN]; // pair(distance, node). Length is 0 for all nodes except neighbours of centroid
int pd[MAXN]; // distance from centroid
int mid3[MAXN]; // exclude the centroid + neighbours
int belg[MAXN]; // which subtree a node belongs to

std::vector<int> createFunTour(int N, int Q) {
  int rt=0;
  vpi T;
  for(int i=1;i<N;++i){
  	T.pb(mp(attractionsBehind(0,i),i));
  }
  sort(ALL(T));reverse(ALL(T));
  while(T.size()&&T.back().f<=N/2)T.pop_back();

  int cent=rt;
  if(SZ(T)==0)cent=rt;
  else{
  	cent=T.back().s;
  }
  belg[cent]=-1;
  vi adj;
  for(int i=0;i<N;++i){
  	int d=hoursRequired(cent,i);
  	pd[i]=d;
  	if(d==1){
  		adj.pb(i);
  		mid3[i]=1;
  	}
  }
  mid3[cent]=1;
  assert(SZ(adj)<=3);
  for(int i=0;i<N;++i)if(!mid3[i]){
  	int done=0;
  	for(auto x:adj)if(x!=adj.back()){
  		int k=hoursRequired(x,i);
  		if(k==pd[i]-1){
  			V[x].pb(mp(pd[i],i));
  			done=1;
  			break;
  		}
  	}
  	if(!done)V[adj.back()].pb(mp(pd[i],i));
  }
  for(auto i:adj){
  	V[i].pb(mp(pd[i],i));
  	sort(ALL(V[i]));
  }
  for(auto i:adj)for(auto j:V[i]){
  	belg[j.s]=i;
  }
  int blk=-1;
  int LFT=N;

  while(SZ(res) < N){
  	int skip=0;
  	int biggst=adj[0];
  	for(auto i:adj)if(SZ(V[i]) > SZ(V[biggst]))biggst=i;
  	int rst=LFT-SZ(V[biggst]);
  	int tx=SZ(V[biggst]);
  	if(tx==rst)skip=1;

  	if(skip){ // Dominant case
  		int MAJ=adj[0];
  		for(auto i:adj)if(SZ(V[i]) > SZ(V[MAJ]))MAJ=i;

  		if(blk!=MAJ){
  			pi t=mp(-1,-1);
  			for(auto i:adj)if(i!=blk){
  				if(SZ(V[i])){
  					pi x=V[i].back();
  					t=max(t,x);
  				}
  			}
  			if(t.s!=MAJ && t.f!=-1 && SZ(res) && pd[res.back()] < t.f){
          // Swap over to other, taller small branch
  			  res.pb(t.s);
  				V[belg[t.s]].pop_back();
  				blk=-1;
  			}
  		}
  		vpi rest;
  		for(auto i:adj)if(i!=MAJ){
  			for(auto k:V[i])rest.pb(k);
  		}
  		rest.pb(-1,cent);
  		sort(ALL(rest));

  		while(SZ(res)<N){
  			if(blk==MAJ){
  				blk=-1;
  				res.pb(rest.back().s);
  				rest.pop_back();
  			}else{
  				res.pb(V[MAJ].back().s);
  				V[MAJ].pop_back();
  				blk=MAJ;
  			}
  		}
  		return res;
  	}
  	else{ // Greedily go to bigest branch that is not currently visited
  		int furtbst=-1;
  		int t=-1;
  		int tp=-1;
  		for(auto i:adj)if(SZ(V[i])){
  			if(i==blk)continue;
  			int k=V[i].back().s;
  			int cd=V[i].back().f;
  			if(cd>=furtbst){
  				furtbst=cd;
  				t=k;
  				tp=i;
  			}
  		}
  		if(t==-1){
  			res.pb(cent);
  			assert(SZ(res)==N);
  			return res;
  		}

  		blk=tp;
  		res.pb(t);
  		V[tp].pop_back();
  	}
  	--LFT;
  }

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