답안 #56303

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
56303 2018-07-11T03:23:33 Z Yehezkiel CEOI16_icc (CEOI16_icc) C++11
90 / 100
198 ms 892 KB
#include "icc.h"
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(),(x).end()
typedef pair<int,int> pii;
const int MAXN=100;
int par[MAXN+5],n;
int finds(int x){
	if(par[x]!=x)
		par[x]=finds(par[x]);
	return par[x];
}
bool connected(int u,int v){
	return (finds(u)==finds(v));
}
void gabung(int u,int v){
	u=finds(u),v=finds(v);
	if(u==v)
		return;
	par[v]=u;
}
int tanya(vector <int> a,vector <int> b){				//O(N)
	int arr1[105];int arr2[105];
	for(int i=0;i<(int) a.size();i++)
		arr1[i]=a[i];
	for(int i=0;i<(int) b.size();i++)
		arr2[i]=b[i];
	
	return query(a.size(),b.size(),arr1,arr2);
}
void print(vector <int> arr){
	cout<<"printing arr"<<endl;
	for(int i=0;i<(int) arr.size();i++)
		cout<<arr[i]<<" ";
	cout<<endl;
}
void expand(vector <int> &vec){		//isinya cuman kepala suku	O(N)
	bool root[MAXN+5];
	for(int i=1;i<=n;i++)
		root[i]=false;
	for(auto isi:vec)
		root[isi]=true;
	vec.clear();
	for(int i=1;i<=n;i++)
		if(root[finds(i)])
			vec.pb(i);
}
void shrink(vector <int> &vec){
	int n=0;
	for(int i=0;i<(int) vec.size();i++)
	{
		if(par[vec[i]]==vec[i])
			vec[n++]=vec[i];
	}
	vec.resize(n);
}
void masukkan(vector <int> &tampung,const vector <int> tambahan){
	for(int isi:tambahan)
		tampung.pb(isi);
}
int perkecil(vector <int> now,const vector <int> other){			//O(NlogN)
	int nomor[MAXN+5],n=0;
	for(int i=0;i<(int) now.size();i++)
	{
		if(now[i]==par[now[i]])
			nomor[now[i]]=n++;
	}
	
	vector <vector <int> > temp1,temp2;
	temp1.resize(n),temp2.resize(n);
	for(int i=0;i<(int) now.size();i++)
		temp1[nomor[finds(now[i])]].pb(now[i]);
	
	while(true)				//O(logN)
	{
		int total=0,lebih=0;
		for(int i=0;i<n;i++)
		{
			total+=temp1[i].size();
			lebih+=temp1[i].size()%2;
		}
		if(total==1)
			break;
		lebih/=2;
		//cout<<totalnya "<<total<<endl;
		
		now.clear();
		for(int i=0;i<n;i++)
		{
			random_shuffle(all(temp1[i]));
			int ambil=temp1[i].size()/2;
			if(temp1[i].size()&1&&lebih)
				ambil++,lebih--;
			temp2[i].clear();
			for(int j=ambil;j<(int) temp1[i].size();j++)
				temp2[i].pb(temp1[i][j]);
			temp1[i].resize(ambil);
			
			masukkan(now,temp1[i]);
		}
		assert(lebih==0);
		assert(abs( (int)now.size() - ( total - (int)now.size() ) )<=1);
		if(tanya(now,other)==0)				//O(N)
		{
			for(int i=0;i<n;i++)
				temp1[i]=temp2[i];
		}
	}
	for(int i=0;i<n;i++)
	{
		if(temp1[i].size()==1)
			return temp1[i][0];
	}
	assert(false);
	return 0;
}

void bagiDua(vector <int> &vec,int &lebih,vector<vector<int> > &tampung){
	random_shuffle(all(vec));
	int ambil=vec.size()/2;
	if(lebih&&(vec.size()&1))
		lebih--,ambil++;
	
	vector <int> kiri,kanan;
	for(int i=0;i<(int) vec.size();i++)
	{
		if(i<ambil)
			kiri.pb(vec[i]);
		else
			kanan.pb(vec[i]);
	}
	tampung.pb(kiri);tampung.pb(kanan);
}
vector <int> kiri,kanan;
void findAnggota(){
	vector <vector <int> > anggota,baru;
	anggota.resize(1);
	for(int i=1;i<=n;i++)
	{
		if(par[i]==i)
			anggota[0].pb(i);
	}
	
	//cout<<"MULAI"<<endl;
	for(int loop=0;;loop++)
	{
		baru.clear();
		int lebih=0;
		for(auto &isi:anggota)
			lebih+=isi.size()%2;
		lebih/=2;
		
		int terbesar=-1;
		for(auto &isi:anggota)
		{
			terbesar=max(terbesar,(int) isi.size());
			bagiDua(isi,lebih,baru);
		}
		assert(terbesar>1);
		
		kiri.clear();kanan.clear();
		for(int i=0;i<(int) baru.size();i++)
		{
			for(auto isi:baru[i])
			{
				if(i&1)
					kanan.pb(isi);
				else
					kiri.pb(isi);
			}
		}
		assert(lebih==0);
		assert(abs((int) kiri.size() - (int) kanan.size())<=1);
		expand(kiri),expand(kanan);
		if(tanya(kiri,kanan))
			break;
		
		anggota=baru;
	}
}
void run(int _n){
	srand(2006);
	n=_n;
	for(int i=1;i<=n;i++)
		par[i]=i;
	
	for(int i=0;i<n-1;i++)
	{
		findAnggota();
		//cout<<"found"<<endl;
		pii ans;
		ans=mp(perkecil(kiri,kanan),perkecil(kanan,kiri));
		setRoad(ans.fi,ans.se);
		gabung(ans.fi,ans.se);
	}
}
# 결과 실행 시간 메모리 Grader output
1 Correct 8 ms 504 KB Ok! 101 queries used.
2 Correct 8 ms 696 KB Ok! 100 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 46 ms 696 KB Ok! 545 queries used.
2 Correct 70 ms 764 KB Ok! 706 queries used.
3 Correct 61 ms 820 KB Ok! 687 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 154 ms 884 KB Ok! 1431 queries used.
2 Correct 190 ms 884 KB Ok! 1700 queries used.
3 Correct 147 ms 884 KB Ok! 1486 queries used.
4 Correct 150 ms 884 KB Ok! 1522 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 171 ms 884 KB Ok! 1459 queries used.
2 Correct 146 ms 884 KB Ok! 1487 queries used.
3 Correct 165 ms 884 KB Ok! 1650 queries used.
4 Correct 144 ms 884 KB Ok! 1436 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 164 ms 892 KB Ok! 1630 queries used.
2 Correct 185 ms 892 KB Ok! 1654 queries used.
3 Correct 198 ms 892 KB Ok! 1655 queries used.
4 Correct 162 ms 892 KB Ok! 1624 queries used.
5 Correct 174 ms 892 KB Ok! 1492 queries used.
6 Correct 173 ms 892 KB Ok! 1556 queries used.
# 결과 실행 시간 메모리 Grader output
1 Incorrect 184 ms 892 KB Too many queries! 1651 out of 1625
2 Halted 0 ms 0 KB -