This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include "minerals.h"
#include <algorithm>
#include <iostream>
#include <numeric>
#include <cassert>
#include <random>
#include <vector>
#include <queue>
typedef long long llong;
const int MAXN = 86000 + 10;
const int INF = 1e9;
int n;
struct Node
{
int idx;
int level;
int l, r;
int qL, qR;
};
int perm[MAXN];
bool isIn[MAXN];
std::vector <int> unique;
std::vector <int> second;
std::vector <int> secondCopy;
std::deque <Node> waitlist;
std::mt19937 rng(69420);
int countDiff;
int query(int idx)
{
isIn[idx] ^= 1;
return countDiff = Query(perm[idx]);
}
void answer(int a, int b)
{
Answer(perm[a], perm[b]);
}
void Solve(int N)
{
n = N;
std::iota(perm + 1, perm + 1 + 2 * n, 1);
std::shuffle(perm + 1, perm + 1 + 2 * n, rng);
unique.push_back(0);
unique.push_back(1);
second.push_back(0);
query(1);
int last = 1;
for (int i = 2 ; i <= 2 * n ; ++i)
{
if (query(i) > last)
{
last++;
unique.push_back(i);
} else
{
second.push_back(i);
}
}
waitlist.push_front({1, 1, 1, n, 1, n});
assert(unique.size() == n + 1);
assert(second.size() == n + 1);
secondCopy.resize(n + 1);
int ptr = n;
int lastLevel = 1;
int reversed = 1;
while (waitlist.size())
{
auto [idx, level, l, r, qL, qR] = waitlist.front();
if (level != reversed)
{
reversed = level;
std::reverse(waitlist.begin(), waitlist.end());
continue;
}
waitlist.pop_front();
assert(r - l + 1 == qR - qL + 1);
if (l == r)
{
assert(qL == qR);
answer(unique[l], second[qL]);
continue;
}
int mid = (l + r) / 2;
if (level != lastLevel)
{
if (level & 1)
{
while (ptr < mid)
{
ptr++;
query(unique[ptr]);
}
} else
{
while (ptr > mid)
{
query(unique[ptr]);
ptr--;
}
}
lastLevel = level;
}
if (level & 1)
{
while (ptr > mid)
{
query(unique[ptr]);
ptr--;
}
} else
{
while (ptr < mid)
{
ptr++;
query(unique[ptr]);
}
}
int myL = qL;
int myR = qR;
for (int idx = qL ; idx <= qR ; ++idx)
{
int last = countDiff;
int curr = query(second[idx]);
if (curr == last)
{
secondCopy[myL++] = second[idx];
} else
{
secondCopy[myR--] = second[idx];
}
}
for (int idx = qL ; idx <= qR ; ++idx)
{
second[idx] = secondCopy[idx];
}
assert(qL < myL);
assert(myR < qR);
if (level & 1)
{
waitlist.push_back({2 * idx + 1, level + 1, mid + 1, r, myR + 1, qR});
waitlist.push_back({2 * idx, level + 1, l, mid, qL, myL - 1});
} else
{
waitlist.push_back({2 * idx, level + 1, l, mid, qL, myL - 1});
waitlist.push_back({2 * idx + 1, level + 1, mid + 1, r, myR + 1, qR});
}
}
}
Compilation message (stderr)
In file included from /usr/include/c++/10/cassert:44,
from minerals.cpp:5:
minerals.cpp: In function 'void Solve(int)':
minerals.cpp:68:26: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
68 | assert(unique.size() == n + 1);
| ~~~~~~~~~~~~~~^~~~~~~~
minerals.cpp:69:26: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
69 | assert(second.size() == n + 1);
| ~~~~~~~~~~~~~~^~~~~~~~
# | 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... |
# | 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... |