QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#743769 | #9734. Identify Chord | Fresca# | WA | 4ms | 3820kb | C++20 | 5.9kb | 2024-11-13 19:58:59 | 2024-11-13 19:59:01 |
Judging History
answer
#include <algorithm>
#include <cassert>
#include <cctype>
#include <iostream>
#include <map>
#include <vector>
#if __cplusplus >= 202002l
#include <format>
#endif
#define int long long
using ull = unsigned long long;
using ll = long long;
using pii = std::pair<int, int>;
// clang-format off
ll read()
{
ll x=0,f=1;char ch=std::cin.get();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=std::cin.get();}
while(isdigit(ch)){x=x*10+ch-'0';ch=std::cin.get();}
return x*f;
}
template<typename T>
void read(std::vector<T> &vr,int n){for(int i=1;i<=n;++i)vr.push_back(read());}
template<typename T>
void read(std::vector<T> &vr,int a,int b){for(int i=a;i<=b;++i)vr[i]=read();}
// clang-format on
void solve()
{
int n = read();
std::map<pii, int> memory;
auto next = [&](int x, int d) -> int
{
x += d;
x = (x - 1) % n + 1;
return x;
};
auto pre = [&](int x, int d) -> int
{
x -= d;
assert(d <= n);
x = (x - 1 + n) % n + 1;
return x;
};
auto close = [&](int a, int b) -> bool
{
return a == b || next(a, 1) == b || pre(a, 1) == b;
};
auto ask = [&](int a, int b) -> int
{
if (close(a, b))
return a == b ? 0 : 1;
if (b < a)
std::swap(a, b);
if (memory.contains({a, b}))
return memory[{a, b}];
std::cout << std::format("? {} {}", a, b) << std::endl;
int temp;
std::cin >> temp;
memory[{a, b}] = temp;
return temp;
};
auto ans = [&](int a, int b) -> void
{
std::cout << std::format("! {} {}", a, b) << std::endl;
int sta = read();
if (sta == -1)
exit(0);
};
auto dist = [&](int a, int b) -> int
{
int temp = abs(b - a);
return std::min(n - temp, temp);
};
auto lenth = [&](int a, int b) -> int
{
if (a > b)
b += n;
return b - a;
};
int fixed = 1;
if (n <= 10)
{
for (int i = 1; i <= n; ++i)
for (int j = i + 1; j <= n; ++j)
if (i != j && next(i, 1) != j && pre(i, 1) != j && ask(i, j) == 1)
{
ans(i, j);
return;
}
}
else
while (true)
{
int firstQuery = next(fixed, n / 2);
int oppodist = ask(fixed, firstQuery);
if (oppodist == n / 2)
{
fixed = next(fixed, 2);
continue;
}
int needDist = dist(firstQuery, fixed) - oppodist;
auto binarySearch = [&](int l, int r, int isRight) -> int
{
auto check = [&](int a) -> int
{
int oriDist = dist(a, fixed);
int trueDist = ask(fixed, a);
return needDist == oriDist - trueDist;
};
while (r - l > 1)
{
int mid = next(l, lenth(l, r) / 2);
if (check(mid) ^ isRight)
r = mid;
else
l = mid;
}
return (isRight ? l : r);
};
int oppo1dist = ask(fixed, next(firstQuery, 1));
int oppo2dist = ask(fixed, pre(firstQuery, 1));
needDist = std::max(dist(fixed, next(firstQuery, 1)) - oppo1dist, needDist);
needDist = std::max(dist(fixed, pre(firstQuery, 1)) - oppo2dist, needDist);
int idOfValley, idOfAnother1, idOfAnother2, idOfAnother3, idOfAnother4, idOfAnother5;
if (oppo1dist > oppodist || oppodist > oppo2dist) // left
{
idOfValley = binarySearch(0, firstQuery, 0);
idOfAnother1 = pre(idOfValley, needDist + 1);
idOfAnother2 = next(idOfValley, needDist + 2 * dist(firstQuery, idOfValley) + 1);
idOfAnother4 = next(idOfAnother2, 1);
idOfAnother5 = pre(idOfAnother2, 1);
idOfAnother3 = pre(idOfAnother1, needDist + 1);
}
else if (oppo1dist < oppodist || oppodist < oppo2dist) // right
{
idOfValley = binarySearch(firstQuery, n + 1, 1);
idOfAnother1 = next(idOfValley, needDist + 1);
idOfAnother2 = pre(idOfValley, needDist + 2 * dist(firstQuery, idOfValley) + 1);
idOfAnother4 = pre(idOfAnother2, 1);
idOfAnother5 = next(idOfAnother2, 1);
idOfAnother3 = next(idOfAnother1, needDist + 1);
}
else
{
__builtin_unreachable();
}
if (!close(idOfValley, idOfAnother1) && ask(idOfValley, idOfAnother1) == 1)
{
ans(idOfValley, idOfAnother1);
return;
}
else if (!close(idOfValley, idOfAnother3) && ask(idOfValley, idOfAnother3) == 1)
{
ans(idOfValley, idOfAnother3);
return;
}
else if (!close(idOfValley, idOfAnother4) && ask(idOfValley, idOfAnother4) == 1)
{
ans(idOfValley, idOfAnother4);
return;
}
else if (!close(idOfValley, idOfAnother5) && ask(idOfValley, idOfAnother5) == 1)
{
ans(idOfValley, idOfAnother5);
return;
}
else
{
ans(idOfValley, idOfAnother2);
return;
}
}
}
signed main()
{
#ifdef Fresca1
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
std::cin.tie(nullptr)->sync_with_stdio(false);
int T = read();
while (T--)
solve();
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3820kb
input:
2 6 2 2 2 1 1 4 1 1
output:
? 1 3 ? 1 4 ? 1 5 ? 2 4 ! 2 4 ? 1 3 ! 1 3
result:
ok ok (2 test cases)
Test #2:
score: -100
Wrong Answer
time: 4ms
memory: 3680kb
input:
1000 15 5 6 6 3 5 1 1 19 5 4 6 5 3 4 5 3 1 1 17 5 4 6 5 3 4 5 2 1 1 15 6 7 5 2 1 1 14 5 6 4 3 3 2 1 1 15 3 2 4 4 3 3 3 1 1 17 8 6 5 7 3 4 4 4 1 1 20 6 7 5 2 3 1 1 13 5 6 4 2 4 2 4 1 1 18 3 2 4 5 3 1 1 13 4 3 5 3 2 1 1 14 2 3 3 3 4 3 2 2 1 17 8 4 5 5 2 5 6 1 1 12 5 4 5 3 3 2 2 2 1 10 2 3 4 5 4 3 2 2 ...
output:
? 1 8 ? 1 9 ? 1 7 ? 1 4 ? 1 6 ? 5 8 ! 8 5 ? 1 10 ? 1 11 ? 1 9 ? 1 15 ? 1 12 ? 1 13 ? 12 18 ? 5 12 ? 3 12 ! 12 3 ? 1 9 ? 1 10 ? 1 8 ? 1 13 ? 1 11 ? 1 12 ? 11 16 ? 4 11 ? 3 11 ! 11 3 ? 1 8 ? 1 9 ? 1 7 ? 1 4 ? 1 3 ! 3 1 ? 1 8 ? 1 9 ? 1 7 ? 1 4 ? 1 6 ? 1 5 ? 2 5 ! 5 2 ? 1 8 ? 1 9 ? 1 7 ? 1 12 ? 1 10 ? 9...
result:
wrong answer Wrong answer n=15, actual=13-15, guessed=1-3 (test case 152)