This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
/**
* Let's see how we can do this interactive problem (looks like to be the only
* interactive task in IOI 2016). The grader is non-adaptive, so it's possible to
* develop randomized solutions. OK, let's see.
*
* Give 10...0, 110...0, 1110...0, ..., 111.10. Can we test one single bit per read
* operation? Hmmm. To find a random bit in n locations, the expected num is
* (1+2+3+...+(n-1)+(n-1))/n = ((n+1) * n / 2 - 1) / n = (n+1)/2 - 1/n. To locate
* all bits, we need (n+1)/2 + n/2 + ... + 2/2 - (sth) ~ (n+3)*n/4-n*log(n) = O(n^2).
* Too much, of course.
*
* Well, i guess it may be a divide & conquer problem (due to n=2^b,
* 896 = 128 * log_2(128)). Can i first put in 1111..10000..0 and determine where do
* the first n/2 1s go? Ah, what about also putting 0111..11000..0? In that way, the
* difference between the images (of these two strs) would be the position the 1st
* and (n+1)-th bit end up. Good.
*
* I will now wrap up my solution. Suppose that n=4. We first ask 1000, 0100 and
* we'll know where the first 2 bits are sent to. (well, we also know about the
* last 2 bits too.) Then, we ask 1011 and 1110 to know where the 1st and 3rd bits
* are sent to. Done.
*
* Write op needed: n * log_2(n) / 2 (not tight)
* Read op needed: n * log_2(n) (tight)
* Implementation 1
*/
#include <bits/stdc++.h>
#include "messy.h"
int n;
void add(int a, int b) { // [a, b)
int mid = (a + b) / 2;
std::string s(n, '1');
for (int i = a; i < mid; i++) {
for (int j = a; j < b; j++)
s[j] = (i == j ? '1' : '0');
add_element(s);
}
if (b - a > 2) {
add(a, mid);
add(mid, b);
}
}
std::vector<int> perm; // perm[i] = where i is sent to (different from the output)
void solve(int a, int b) { // [a, b)
int k = b - a, mid = (a + b) / 2;
std::string s(n, '1');
std::set<int> A, B;
for (int i = a; i < b; i++) {
for (int j = a; j < b; j++)
s[perm[j]] = (i == j ? '1' : '0');
if (check_element(s))
A.emplace(perm[i]);
}
for (int i = a; i < b; i++) {
if (A.find(perm[i]) == A.end())
B.emplace(perm[i]);
}
assert(int(A.size()) == k / 2 && int(B.size()) == k / 2);
int i = a;
for (int v : A)
perm[i++] = v;
for (int v : B)
perm[i++] = v;
if (b - a > 2) {
solve(a, mid);
solve(mid, b);
}
}
std::vector<int> restore_permutation(int _n, int w, int r) {
n = _n;
add(0, n);
compile_set();
perm.resize(n);
for (int i = 0; i < n; i++)
perm[i] = i;
solve(0, n);
std::vector<int> ans(n);
for (int i = 0; i < n; i++)
ans[perm[i]] = i;
return ans;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |