Repository navigation
Expand file tree
/
Copy pathsolver.hpp
More file actions
100 lines (100 loc) · 2.17 KB
/
Copy pathsolver.hpp
File metadata and controls
100 lines (100 loc) · 2.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Setter: repeated-pivot substring queries and binary search for neighbors.
// GPT-6: endpoint growth, explicit protocol, safe sizing, and query-bound proof.
#pragma once
#include <algorithm>
#include <deque>
#include <numeric>
#include <vector>
template<class FAsk>
std::vector<int> RecoverPermutation(int n, FAsk Ask)
{
if (n == 1)
{
return {1};
}
std::vector<int> Candidates(n - 1);
std::iota(Candidates.begin(), Candidates.end(), 2);
// At least one of the two neighbors of 1 is in this candidate set.
while (Candidates.size() > 1)
{
int Half = std::min(49, static_cast<int>(Candidates.size()) / 2);
std::vector<int> Query{1};
for (int i = 0; i < Half; ++i)
{
Query.push_back(Candidates[i]);
Query.push_back(1);
}
if (Ask(Query) >= 2)
{
Candidates.resize(Half);
}
else
{
Candidates.erase(Candidates.begin(), Candidates.begin() + Half);
}
}
int Neighbor = Candidates[0];
std::deque<int> Chain;
if (Ask(std::vector<int>{1, Neighbor}) == 2)
{
Chain = {1, Neighbor};
}
else
{
Chain = {Neighbor, 1};
}
std::vector<bool> Used(n + 1, false);
Used[1] = true;
Used[Neighbor] = true;
bool bRight = true;
while (static_cast<int>(Chain.size()) < n)
{
Candidates.clear();
for (int Value = 1; Value <= n; ++Value)
{
if (!Used[Value])
{
Candidates.push_back(Value);
}
}
int Endpoint = bRight ? Chain.back() : Chain.front();
bool bExists = false;
while (!Candidates.empty() && (!bExists || Candidates.size() > 1))
{
int Half = std::min(50, (static_cast<int>(Candidates.size()) + (bExists ? 0 : 1)) / 2);
std::vector<int> Query;
for (int i = 0; i < Half; ++i)
{
Query.push_back(bRight ? Endpoint : Candidates[i]);
Query.push_back(bRight ? Candidates[i] : Endpoint);
}
if (Ask(Query) >= 2)
{
Candidates.resize(Half);
bExists = true;
}
else
{
Candidates.erase(Candidates.begin(), Candidates.begin() + Half);
}
}
if (Candidates.empty())
{
bRight = false;
}
else
{
int Value = Candidates[0];
Used[Value] = true;
if (bRight)
{
Chain.push_back(Value);
}
else
{
Chain.push_front(Value);
}
}
}
return std::vector<int>(Chain.begin(), Chain.end());
}