[QOJ 10072] Around the Table
乱搞做法,不喜勿喷。
首先考虑 \(\operatorname{random}\) \(60\) 个排列,一次性询问完,相当于我们现在将一个点和它的两个邻居连一条边,我们要求这个图上的一个哈密顿回路?
然后考虑用一些条件找出来这些邻居。
首先,若 \(u\) 和 \(v\) 在同一次中被返回了 \(1\),则他们不能成为邻居。
这样会筛掉很多的情况。
考虑对于一个 \(u\),若 \(u\) 在某一次询问中被返回 \(1\),那么在它之前的所有的备选的邻居全部不合法,删掉。
然后直接建图过后跑哈密顿回路?
然后用一个 bitset 优化一下时间,然后就过了?
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
int n;
int32_t M[MAXN][60];
int P[MAXN];
uint64_t R[MAXN];
bitset<MAXN> B[60];
vector<int> C[MAXN];
set<int> adj[MAXN];
vector<int> sym_adj[MAXN];
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> n;
if (n == 1) { cout << "! 1\n"; cout.flush(); return 0; }
if (n == 2) { cout << "! 1 2\n"; cout.flush(); return 0; }
if (n == 3) { cout << "! 1 2 3\n"; cout.flush(); return 0; }
mt19937 rng(1337);
for (int q = 0; q < 60; ++q) {
iota(P + 1, P + n + 1, 1);
shuffle(P + 1, P + n + 1, rng);
for (int i = 1; i <= n; ++i) {
M[P[i]][q] = i;
}
cout << "?";
for (int i = 1; i <= n; ++i) cout << " " << P[i];
cout << "\n";
cout.flush();
int k;
cin >> k;
if (k == -1) exit(0);
B[q].set();
for (int i = 0; i < k; ++i) {
int u;
cin >> u;
R[u] |= (1ULL << q);
B[q].reset(u);
}
}
for (int i = 1; i <= n; ++i) {
bitset<MAXN> cand;
cand.set();
for (int q = 0; q < 60; ++q) {
if ((R[i] >> q) & 1) {
cand &= B[q];
}
}
cand.reset(i);
for (int j = cand._Find_first(); j < cand.size(); j = cand._Find_next(j)) {
if (i < j) {
bool ok = true;
for (int q = 0; q < 60; ++q) {
if (((R[i] >> q) & 1) && M[i][q] > M[j][q]) { ok = false; break; }
if (((R[j] >> q) & 1) && M[j][q] > M[i][q]) { ok = false; break; }
}
if (ok) {
C[i].push_back(j);
C[j].push_back(i);
}
}
}
}
for (int i = 1; i <= n; ++i) {
int sz = C[i].size();
for (int x = 0; x < sz; ++x) {
int v1 = C[i][x];
for (int y = x + 1; y < sz; ++y) {
int v2 = C[i][y];
bool ok = true;
for (int q = 0; q < 60; ++q) {
if (!((R[i] >> q) & 1)) {
if (M[v1][q] > M[i][q] && M[v2][q] > M[i][q]) {
ok = false;
break;
}
}
}
if (ok) {
adj[i].insert(v1);
adj[i].insert(v2);
}
}
}
}
for (int i = 1; i <= n; ++i) {
for (int v : adj[i]) {
if (adj[v].count(i)) {
sym_adj[i].push_back(v);
}
}
}
vector<int> path;
vector<bool> vis(n + 1, false);
struct State {
int u;
size_t idx;
};
vector<State> st;
int start = 1;
st.push_back({ start, 0 });
vis[start] = true;
path.push_back(start);
bool found = false;
while (!st.empty()) {
if (path.size() == (size_t)n) {
bool connects = false;
for (int v : sym_adj[st.back().u]) {
if (v == start) { connects = true; break; }
}
if (connects) {
found = true;
break;
}
else {
st.back().idx = sym_adj[st.back().u].size();
}
}
if (st.back().idx < sym_adj[st.back().u].size()) {
int v = sym_adj[st.back().u][st.back().idx++];
if (!vis[v]) {
vis[v] = true;
path.push_back(v);
st.push_back({ v, 0 });
}
}
else {
vis[st.back().u] = false;
path.pop_back();
st.pop_back();
}
}
cout << "!";
if (found)
for (int x : path) cout << " " << x;
else
for (int i = 1; i <= n; ++i) cout << " " << i;
cout << "\n";
cout.flush();
return 0;
}

浙公网安备 33010602011771号