답안 #62217

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
62217 2018-07-27T21:28:20 Z kingpig9 CEOI16_icc (CEOI16_icc) C++11
100 / 100
195 ms 892 KB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include "icc.h"

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
template<class T> using ordset = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
const int MAXN = 110;

#define debug(...) fprintf(stderr, __VA_ARGS__)
#define fi first
#define se second
#define all(v) (v).begin(), (v).end()
#define fillchar(a, s) memset((a), (s), sizeof(a))

struct union_find {
	int par[MAXN];

	void init() {
		for (int i = 0; i < MAXN; i++) {
			par[i] = i;
		}
	}

	int find (int x) {
		return x == par[x] ? x : par[x] = find(par[x]);
	}

	void merge (int x, int y) {
		par[find(x)] = find(y);
	}
} uf;

int N;
int tmpa[MAXN], tmpb[MAXN];
vector<int> verts[MAXN];

int query (vector<int> a, vector<int> b) {
	copy(all(a), tmpa);
	copy(all(b), tmpb);
	return query(a.size(), b.size(), tmpa, tmpb);
}

vector<int> getverts (vector<int> vc) {
	vector<int> v;
	for (int c : vc) {
		v.insert(v.end(), all(verts[c]));
	}
	return v;
}

int queryc (vector<int> ca, vector<int> cb) {
	return query(getverts(ca), getverts(cb));
}

pii findedge() {
#warning reset!
	for (int i = 1; i <= N; i++) {
		verts[i].clear();
	}
	vector<int> reps;
	for (int i = 1; i <= N; i++) {
		verts[uf.find(i)].push_back(i);
		if (i == uf.find(i)) {
			reps.push_back(i);
		}
	}

	//ok while it is true
	//which bit does it differ in?
	int xoedge = 0;	//xor of edge
	int nbt = 7;
	for (int bt = 0; bt < 7; bt++) {
		//bt = bit that it differs by
		vector<int> vca, vcb;
		for (int i = 0; i < reps.size(); i++) {
			if (i & (1 << bt)) {
				vca.push_back(reps[i]);
			} else {
				vcb.push_back(reps[i]);
			}
		}

		if (!vca.empty() && !vcb.empty()) {
			xoedge ^= (queryc(vca, vcb) << bt);
		} else {
			nbt = bt;
			break;
		}
	}

	int bd = __builtin_ctz(xoedge);	//bit that is different
	int cmpa = 0, cmpb = (1 << bd);
	for (int bt = 0; bt < nbt; bt++) {
		if (bt == bd) {
			continue;
		}

		vector<int> vca, vcb;
		if (xoedge & (1 << bt)) {
			//they differ in this bit
			for (int i = 0; i < reps.size(); i++) {
				int bibt = (i >> bt) & 1;	//bit of i that is at position bt
				int bibd = (i >> bd) & 1;	//bit of i that is at position bd
				if (bibt == 0 && bibd == 0) {
					vca.push_back(reps[i]);
				} else if (bibt == 1 && bibd == 1) {
					vcb.push_back(reps[i]);
				}
			}

			if (queryc(vca, vcb)) {
				//then yes. cmpa has this bit as 0, cmpb has this bit as 1.
				cmpb ^= (1 << bt);
			} else {
				cmpa ^= (1 << bt);
			}
		} else {
			//they are same in this bit. is it zero or one?
			for (int i = 0; i < reps.size(); i++) {
				int bibt = (i >> bt) & 1;	//bit of i that is at position bt
				int bibd = (i >> bd) & 1;	//bit of i that is at position bd
				if (bibt == 0) {
					if (bibd == 0) {
						vca.push_back(reps[i]);
					} else {
						vcb.push_back(reps[i]);
					}
				}
			}

			if (queryc(vca, vcb)) {
				//"bt" is zero
			} else {
				//"bt" is one
				cmpa ^= (1 << bt);
				cmpb ^= (1 << bt);
			}
		}
	}

	vector<int> va = verts[reps[cmpa]], vb = verts[reps[cmpb]];;
	while (va.size() > 1) {
		int half = va.size() / 2;
		if (query(vector<int> (va.begin(), va.begin() + half), vb)) {
			va.resize(half);
		} else {
			va.erase(va.begin(), va.begin() + half);
		}
	}

	while (vb.size() > 1) {
		int half = vb.size() / 2;
		if (query(va, vector<int> (vb.begin(), vb.begin() + half))) {
			vb.resize(half);
		} else {
			vb.erase(vb.begin(), vb.begin() + half);
		}
	}

	//ok now we have the components
	//get down to vertices
	return pii(va[0], vb[0]);
}

void run (int nnnnn) {
	N = nnnnn;
	uf.init();
	//just randomize it lol
	for (int i = 0; i < N - 1; i++) {
		pii p = findedge();
		setRoad(p.fi, p.se);
		uf.merge(p.fi, p.se);
	}
}

Compilation message

icc.cpp:62:2: warning: #warning reset! [-Wcpp]
 #warning reset!
  ^~~~~~~
icc.cpp: In function 'pii findedge()':
icc.cpp:81:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (int i = 0; i < reps.size(); i++) {
                   ~~^~~~~~~~~~~~~
icc.cpp:107:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for (int i = 0; i < reps.size(); i++) {
                    ~~^~~~~~~~~~~~~
icc.cpp:125:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for (int i = 0; i < reps.size(); i++) {
                    ~~^~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 13 ms 504 KB Ok! 117 queries used.
2 Correct 11 ms 504 KB Ok! 117 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 55 ms 776 KB Ok! 646 queries used.
2 Correct 46 ms 776 KB Ok! 552 queries used.
3 Correct 48 ms 776 KB Ok! 591 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 166 ms 800 KB Ok! 1572 queries used.
2 Correct 144 ms 800 KB Ok! 1372 queries used.
3 Correct 195 ms 812 KB Ok! 1613 queries used.
4 Correct 173 ms 876 KB Ok! 1575 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 156 ms 876 KB Ok! 1583 queries used.
2 Correct 156 ms 880 KB Ok! 1544 queries used.
3 Correct 155 ms 880 KB Ok! 1488 queries used.
4 Correct 190 ms 880 KB Ok! 1609 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 152 ms 880 KB Ok! 1414 queries used.
2 Correct 172 ms 880 KB Ok! 1433 queries used.
3 Correct 150 ms 880 KB Ok! 1424 queries used.
4 Correct 158 ms 892 KB Ok! 1452 queries used.
5 Correct 183 ms 892 KB Ok! 1601 queries used.
6 Correct 159 ms 892 KB Ok! 1602 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 159 ms 892 KB Ok! 1448 queries used.
2 Correct 144 ms 892 KB Ok! 1420 queries used.