it's creepy, is there at least an option to turn it off?
# | User | Rating |
---|---|---|
1 | tourist | 4009 |
2 | jiangly | 3823 |
3 | Benq | 3738 |
4 | Radewoosh | 3633 |
5 | jqdai0815 | 3620 |
6 | orzdevinwang | 3529 |
7 | ecnerwala | 3446 |
8 | Um_nik | 3396 |
9 | ksun48 | 3390 |
10 | gamegame | 3386 |
# | User | Contrib. |
---|---|---|
1 | cry | 167 |
2 | Um_nik | 163 |
3 | maomao90 | 162 |
3 | atcoder_official | 162 |
5 | adamant | 159 |
6 | -is-this-fft- | 158 |
7 | awoo | 157 |
8 | TheScrasse | 154 |
9 | Dominater069 | 153 |
9 | nor | 153 |
it's creepy, is there at least an option to turn it off?
TL;DR: I shuffled the array, got 100 points, and have no idea why.
(every instance of BOI here refers to the Baltic Olympiad in Informatics.)
I was working on BOI23 d1p2 yesterday, and came up with the following solution for 50 pts:
if we know the value of $$$\min(a,b)$$$, and query both $$$\min(a,c)$$$ and $$$\min(b,c)$$$, we can easily determine which value is the smallest among $$$a, b, c$$$ (let's assume it's $$$b$$$) and we still know $$$\min(a,c)$$$, so we can restart the process with the next value $$$d$$$ for a total of $$$2n - 1$$$ queries.
#include "bits/stdc++.h"
using namespace std;
int query(int i, int j) {
cout << "? " << i << ' ' << j << "\n";
cout.flush();
int res;
cin >> res;
return res;
}
int main(){
int n;
cin >> n;
int ab = query(1, 2), a = 1, b = 2;
vector<int> sol(n + 1, -1);
for(int c = 3; c <= n; ++c) {
int ac = query(a, c), bc = query(b, c);
if(ac < ab) {
sol[c] = ac;
}
else if(ac > ab) {
sol[b] = ab;
b = c;
ab = ac;
}
else {
sol[a] = ac;
a = c;
ab = bc;
}
}
sol[a] = sol[b] = ab;
cout << "! ";
for(int i = 1; i <= n; ++i) {
cout << sol[i] << ' ';
}
cout.flush();
}
Here, there were 2 obvious optimizations:
Since I only need the value of $$$\min(b, c)$$$ if $$$\min(a, c) = \min(a, b)$$$, we can throw out some unnecessary queries
Might as well randomize the array since it might reduce such occurrences, idk ¯\_(ツ)_/¯
#include "bits/stdc++.h"
using namespace std;
int query(int i, int j) {
cout << "? " << i << ' ' << j << "\n";
cout.flush();
int res;
cin >> res;
return res;
}
mt19937 rng(234981239);
signed main(){
int n;
cin >> n;
vector<int> sol(n + 1, -1), people(n);
iota(people.begin(), people.end(), 1);
shuffle(people.begin(), people.end(), rng);
int ab = query(people[0], people[1]), a = people[0], b = people[1];
for(int i = 2; i < n; ++i) {
int c = people[i];
int ac = query(a, c);
if(ac < ab) {
sol[c] = ac;
}
else if(ac > ab) {
sol[b] = ab;
b = c;
ab = ac;
}
else {
sol[a] = ac;
a = c;
int bc = query(b, c);
ab = bc;
}
}
sol[a] = sol[b] = ab;
cout << "! ";
for(int i = 1; i <= n; ++i) {
cout << sol[i] << ' ';
}
cout.flush();
}
And to my surprise...it got 100 points!
Looking at the official code, this seems to be the intended solution. However, even after thinking on it, I'm not really sure why it works. Why is shuffling the array so effective? (only applying optimization 1 without 2 gets you 58 points.)
I was wondering if there was anything similar to this, but for the practice session that took place today.
Name |
---|