Submission #1204844

#TimeUsernameProblemLanguageResultExecution timeMemory
1204844model_codePermutation Game (APIO25_permgame)C++20
100 / 100
59 ms584 KiB
#include "permgame.h"
#include <bits/stdc++.h>
using namespace std;

#define ii pair<int,int>
#define iii tuple<int,int,int>
#define fi first
#define se second
#define debug(x) cout << #x << ": " << x << endl

#define vi vector<int>
#define vvi vector<vector<int>>
#define zz(x) x.insert(x.begin(),0);

#define pub push_back
#define pob pop_back
#define puf push_front
#define pof pop_front
#define lb lower_bound
#define ub upper_bound

#define rep(x,start,end) for(int x=(start)-((start)>(end));x!=(end)-((start)>(end));((start)<(end)?x++:x--))
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()

int n,m;
int arr[405];

vector<int> al[405];
ii edges[405];

vi chain; //this might be line or cycle

vvi cycs;

int decomp(){
	bool vis[405]={};
	cycs.clear();
	
	rep(x,0,n) if (!vis[x]){
		vi cyc={x};
		while (!vis[cyc.back()]){
			vis[cyc.back()]=true;
			cyc.pub(arr[cyc.back()]);
		}
		cyc.pob();
		cycs.pub(cyc);
	}
	
	sort(all(cycs),[](vi a,vi b){
		return sz(a)>sz(b);
	});
	
	int res=n;
	while (!cycs.empty() && sz(cycs.back())==1){
		res--;
		cycs.pob();
	}
	
	return res;
}

void send(vector<int> v){
	//v is in natural sorted order
	//we need to reshuffle it based on chain
	
	vi move(m);
	rep(x,0,m) move[chain[x]]=v[x];
	int idx=Bob(move);
	swap(arr[move[edges[idx].fi]],arr[move[edges[idx].se]]);
}

void splitOdd(vector<int> v){
	//split an odd cycle of size s>m into [2,s-2] or [1,s-1]
	
	vi res;
	for (int x=0;x<m;x+=2) res.pub(v[x]);
	for (int x=m-2;x>0;x-=2) res.pub(v[x]);
	send(res); 
}

void splitEven(vector<int> v){
	//split an even cycle of size s>=m+2 into [m,s-m] or [1,s-1]
	int s=sz(v);
	
	int curr=0;
	vi res={curr};
	rep(x,0,m/2-1){
		if (curr%(2*(s-m)-2)==0) curr+=s-m;
		else curr++;
		res.pub(curr);
	}
	
	curr++;
	res.pub(curr);
	
	curr-=(s-m);
	res.pub(curr);
	
	rep(x,0,m/2-2){
		if (curr%(2*(s-m)-2)==1) curr-=s-m;
		else curr--;
		res.pub(curr);
	}
	
	for (auto &it:res) it=v[it];
	
	send(res);
}

int Alice(int M, int E, vector<int> U, vector<int> V, int N, vector<int> P){
	n=N,m=M;
	
	rep(x,0,n) arr[x]=P[x];
	
	if (m==2){ //annoying case
		decomp();
		for (auto cyc:cycs) rep(x,1,sz(cyc)) Bob({cyc[0],cyc[x]});
		return n;
	}
	
	rep(x,0,E){
		al[U[x]].pub(V[x]);
		al[V[x]].pub(U[x]);
		edges[x]={U[x],V[x]};
	}
	
	int ans=0;
	rep(x,0,n) ans+=(arr[x]==x);
	
	bool bad=ans>=n-m+1;
	rep(x,0,m) if (sz(al[x])>=3) bad=true;
	
	if (bad) return ans;
	
	int r=0;
	rep(x,0,m) if (sz(al[x])==1) r=x;
	chain={r};
	rep(x,0,m-1){
		for (auto it:al[chain.back()]){
			if (sz(chain)==1 || chain[sz(chain)-2]!=it){
				chain.pub(it);
				break;
			}
		}
	}
	
    if (E+1==m || (m%2==0 && ans==n-m)){ //line graph or even cycle special case
		while (decomp()>=m){
			vi v;
			for (auto cyc:cycs) v.insert(v.end(),all(cyc));
			v.resize(m);
			send(v);
		}
		return n-m+1;
	}
	else if (m%2==1){ //odd cycle
		int goal=n-decomp();
		int odd=0,sz=0,ext=0;
		for (auto cyc:cycs){
			if (sz(cyc)%2==1) odd++;
			else sz+=sz(cyc);
		}
		
		for (auto cyc:cycs){
			if (sz(cyc)%2==1 && sz<m){
				ext++;
				sz+=sz(cyc);
			}
		}
		
		goal+=odd-2*(ext/2);
		
		while (decomp()>n-goal){
			vi v;
			
			//if ther is a big odd cycle, do opearation on them
			for (auto cyc:cycs) if (sz(cyc)%2==1){
				if (sz(cyc)>m){
					splitOdd(cyc);
					goto _done;
				}
				if (sz(cyc)==m){
					send(cyc);
					goto _done;;
				}
			}
			
			//there are no big odd cycles, we should try to combine cycles now
			for (auto cyc:cycs) if (sz(cyc)%2==0) v.insert(v.end(),all(cyc));
			while (sz(v)>m-1) v.pob(); //leave space for the odd cycle
			for (auto cyc:cycs) if (sz(cyc)%2==1) v.insert(v.end(),all(cyc));
			v.resize(m);
			send(v);
			
			_done:;
		}
		
		return goal;
	}
	else{ //even cycle
		while (decomp()>m+1){ //phase 1
			int tot=0;
			vi v;
			
			for (auto cyc:cycs) if (sz(cyc)==m){
				send(cyc);
				goto _done2;
			}
			
			for (auto cyc:cycs) if (sz(cyc)>=m+2){
				splitEven(cyc);
				goto _done2;
			}
			
			//try to combine cycles
			for (auto cyc:cycs) if (sz(cyc)>2) tot+=sz(cyc);
			
			if (tot<m+2) break; //end of phase 1
			
			for (auto cyc:cycs){
				v.insert(v.end(),all(cyc));
				//prevent the entire query being 1 cycle
				if (sz(v)==sz(cyc) && sz(v)>m-1) v.resize(m-1);
			}
			v.resize(m);
			send(v);
			
			_done2:;
		}
		
		while (decomp()>m+1){ //phase 2
			vi v;
			
			for (auto cyc:cycs) if (sz(cyc)==m){
				send(cyc);
				goto _done3;
			}
			
			for (auto cyc:cycs) if (sz(cyc)>=2*m-1){
				splitEven(cyc);
				goto _done3;
			}
			
			if (sz(cycs)==1) break; //end of phase 2
			
			for (auto cyc:cycs){
				v.insert(v.end(),all(cyc));
				//prevent the entire query being 1 cycle
				if (sz(v)==sz(cyc) && sz(v)>m-1) v.resize(m-1);
			}
			v.resize(m);
			send(v);
			
			_done3:;
		}
		
		while (decomp()>m+1){ //phase 3
			if (sz(cycs[0])==m) send(cycs[0]);
			else if (sz(cycs[0])>=m+2) splitEven(cycs[0]);
			else{
				vi v;
				for (auto cyc:cycs) v.insert(v.end(),all(cyc));
				v.resize(m);
				send(v);
			}
		}
		
		return n-m-1;
	}
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...