P6960 题解
EuphoricStar · · 题解
NOIP 模拟赛 T2。随机化交互好题。
令
显然可以使用
考虑我们求出了一个
那么当我们求每一个 check
时和块内任意一个
现在问题是询问次数没有保证。考虑以一个随机的顺序问
const int maxn = 10050;
int n, a[maxn], b[maxn], p[maxn];
struct node {
int l, r;
vector<int> ps;
};
void solve(int _n) {
n = _n;
node u;
u.l = 1;
u.r = (n + 1) / 2 * 2 - 1;
for (int i = 1; i <= (n + 1) / 2; ++i) {
u.ps.pb(i);
}
vector<node> vc;
vc.pb(u);
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
for (int i = 1; i <= n / 2; ++i) {
p[i] = i;
}
shuffle(p + 1, p + n / 2 + 1, rnd);
for (int i = 1; i <= n / 2; ++i) {
int l = 0, r = (int)vc.size() - 1;
while (r - l + 1 > 2) {
int mid = (l + r) >> 1;
if (ask(p[i], vc[mid].ps[0])) {
l = mid;
} else {
r = mid;
}
}
bool flag = 1;
for (int j = l; j <= r; ++j) {
vector<int> v1, v2;
for (int x : vc[j].ps) {
if (ask(p[i], x)) {
v1.pb(x);
} else {
v2.pb(x);
}
}
if (v1.empty() || v2.empty()) {
continue;
}
flag = 0;
if (j) {
a[p[i]] = vc[j - 1].r + 1;
}
a[p[i]] += (int)v1.size() * 2;
node u;
u.l = a[p[i]] + 1;
u.r = vc[j].r;
vc[j].r = a[p[i]] - 1;
vc[j].ps = v1;
u.ps = v2;
vc.insert(vc.begin() + j + 1, u);
break;
}
if (flag) {
a[p[i]] = n;
}
}
for (node u : vc) {
b[u.ps[0]] = u.l;
}
vector<int> v1, v2;
for (int i = 1; i <= n / 2; ++i) {
v1.pb(a[i]);
}
for (int i = 1; i <= (n + 1) / 2; ++i) {
v2.pb(b[i]);
}
report(v1, v2);
}