题解:P15366 [IOI 2013] Cave
masonxiong · · 题解
:::info[简要题面]
有
提供函数 tryCombination(S[]),参数为每个开关的状态,返回所有关闭的门中最小的编号,或者
因为 tryCombination 只会返回关闭的门中最小的编号,所以我们在确定一个门对应的开关和正确状态时应当先将编号比它小的门全部打开来避免影响,于是我们按编号从小到大对于每个门确定它对应的开关和正确状态。
设当前待确定的门为
接下来确定
确定一个门所需要的查询次数为
:::info[code]
#include <bits/extc++.h>
extern "C" int tryCombination(int S[]);
extern "C" void answer(int S[], int D[]);
extern "C" void exploreCave(int N) {
auto n = static_cast<unsigned>(N);
std::vector<int> S(n), D(n);
std::vector<bool> determined(n);
for (auto x = 0U; x != n; ++x) {
std::vector<int> currentS(n);
std::vector<unsigned> undetermined;
for (auto i = 0U; i != n; ++i)
determined[i] ? void(currentS[i] = S[i]) : undetermined.push_back(i);
auto left = 0ULL, right = static_cast<decltype(0ULL)>(undetermined.size());
auto correct = static_cast<unsigned>(tryCombination(currentS.data())) == x;
while (right - left > 1) {
auto middle = (left + right) / 2;
for (auto i = 0U; i != n; ++i)
if (!determined[i])
currentS[i] = !correct;
for (auto i = left; i != middle; ++i)
currentS[undetermined[i]] = correct;
(static_cast<unsigned>(tryCombination(currentS.data())) == x ? left : right) = middle;
}
S[undetermined[left]] = correct;
D[undetermined[left]] = x;
determined[undetermined[left]] = true;
}
answer(S.data(), D.data());
}
:::