제출 #1364826

#제출 시각아이디문제언어결과실행 시간메모리
1364826jinhan814Kirameki of Revue (KAISTRUN26SPRING_E)C++20
100 / 100
564 ms18300 KiB
#include <bits/stdc++.h>
using namespace std;

// debug /*{{{*/
#define debug(...) __dbg(#__VA_ARGS__, __VA_ARGS__)

template<typename T> concept Container = ranges::range<T> && !convertible_to<T, string_view>;
template<typename T, typename U> ostream& operator<<(ostream& out, const pair<T, U>& v);
template<typename... Args> ostream& operator<<(ostream& out, const tuple<Args...>& v);
template<Container T> ostream& operator<<(ostream& out, const T& v);

template<typename T, typename U>
ostream& operator<<(ostream& out, const pair<T, U>& v) {
	out << '(' << v.first << ' ' << v.second << ')';
	return out;
}

template<typename... Args>
ostream& operator<<(ostream& out, const tuple<Args...>& v) {
	string _;
	out << '(';
	apply([&](auto&&... x) { (..., (out << _ << x, _ = " ")); }, v);
	out << ')';
	return out;
}

template<Container T>
ostream& operator<<(ostream& out, const T& v) {
	string _;
	out << '(';
	for (auto i : v) out << _ << i, _ = " ";
	out << ')';
	return out;
}

template<typename ...Args>
void __dbg(string s, Args&&... x) {
	string _;
	cerr << '(' << s << ") : ";
	(..., (cerr << _ << x, _ = ", "));
	cerr << endl;
}
/*}}}*/

using i64 = long long;

auto naive = [](int n, i64 k, auto v) {
	vector c(0, 0);
	for (int i = 0; i < n; i++) {
		for (int j = i + 1; j < n; j++) {
			c.push_back(v[i] ^ v[j]);
		}
	}
	nth_element(c.begin(), c.begin() + k - 1, c.end());
	return c[k - 1];
};

auto sol = [](int n, i64 k, auto v) {
	vector l(1, -1), r(1, -1);
	vector cnt(1, 0);
	int sz = 1;
	for (int i = 0; i < n; i++) {
		int x = v[i];
		cnt[0]++;
		for (int bit = 29, pos = 0; bit >= 0; bit--) {
			if (x >> bit & 1) swap(l[pos], r[pos]);
			if (l[pos] == -1) {
				l.push_back(-1);
				r.push_back(-1);
				cnt.push_back(0);
				sz++;
				l[pos] = sz - 1;
			}
			int npos = l[pos];
			if (x >> bit & 1) swap(l[pos], r[pos]);
			pos = npos;
			cnt[pos]++;
		}
	}
	auto query = [&](int i, int x) {
		/*
		int ret = 0;
		for (int val : v) if ((val ^ x) <= i) ret++;
		return ret;
		*/
		auto rec = [&](const auto& self, int node, int node_l, int node_r, int bit) -> int {
			assert(node_l <= i);
			if (i == node_r) return cnt[node];
			if (x >> bit & 1) swap(l[node], r[node]);
			int mid = (node_l + node_r) / 2;
			int ret = 0;
			if (i <= mid) {
				if (l[node] != -1) ret += self(self, l[node], node_l, mid, bit - 1);
			}
			else {
				if (l[node] != -1) ret += cnt[l[node]];
				if (r[node] != -1) ret += self(self, r[node], mid + 1, node_r, bit - 1);
			}
			if (x >> bit & 1) swap(l[node], r[node]);
			return ret;
		};
		return rec(rec, 0, 0, (1 << 30) - 1, 29);
	};
	auto f = [&](int x) {
		i64 ret = 0;
		for (int i = 0; i < n; i++) ret += query(x, v[i]) - 1;
		ret /= 2;
		return ret;
	};
	int lo = -1, hi = 1 << 30;
	while (lo + 1 < hi) {
		int mid = (lo + hi) / 2;
		if (f(mid) < k) lo = mid;
		else hi = mid;
	}
	return hi;
};

// vgen /*{{{*/
auto gen_rand = [](int l, int r) {
	static mt19937 rd(0x814814);
	return uniform_int_distribution(l, r)(rd);
};

auto gen = [] {
	int lim = 10;
	int n = gen_rand(2, 6);
	i64 k = gen_rand(1, n * (n - 1) / 2);
	vector v(n, 0);
	for (int i = 0; i < n; i++) v[i] = gen_rand(0, lim);
	return tuple(n, k, v);
};

auto test = [] {
	for (int iter = 0; iter < 100'000; iter++) {
		if (iter % 1'000 == 0) debug(iter);
		auto [n, k, v] = gen();
		auto r1 = naive(n, k, v);
		auto r2 = sol(n, k, v);
		if (r1 == r2) continue;
		debug(n);
		debug(v);
		debug(r1);
		debug(r2);
		break;
	}
	exit(0);
};
/*}}}*/

int main() {
	cin.tie(0)->sync_with_stdio(0);
	int n; cin >> n;
	i64 k; cin >> k;
	vector v(n, 0);
	for (int i = 0; i < n; i++) cin >> v[i];
	cout << sol(n, k, v) << '\n';
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…