P9918 题解(2023 激励计划评分 10)
有人觉得 Hard Ver 比 Easy Ver 简单,哎。
设上一次询问的集合
我们维护
根据 Easy Ver 的思路,施二分
否则,
朴素实现是
实际上没有卡交互次数,反正都是期望
Subtask 0 特判乘积为
std::vector<int> S;
inline char query(int l = 1, int r = 0) {
std::cout << "? " << S.size() + (r - l + 1) << ' ';
for (int i : S) std::cout << i << ' ';
for (int i = l; i <= r; ++i) std::cout << i << ' ';
std::cout << std::endl;
char x; std::cin >> x; return x;
}
inline void pb(int l, int r) { for (int i = l; i <= r; ++i) S.push_back(i); }
inline char reverse(char ch) { return ch == '+' ? '-' : ch == '-' ? '+' : ch; }
inline char func(char ch1, char ch2) { return ch1 == '0' ? ch2 : ch1; }
void solve() {
int N, K, Smax; std::cin >> N >> K >> Smax; S.clear();
if (N == 1) {
std::cout << "! 1" << std::endl;
return;
}
pb(1, pos[N]); char lst = query(), Ssgn = lst;
int l = 1, r = N; if (lst == '+') l = pos[N] + 1; else r = pos[N];
while (l < r) {
int mid = l + r >> 1; char now = query(l, mid);
if (now != lst) {
char Nsgn = func(reverse(lst), now);
pb(l, mid);
if (Ssgn == Nsgn) l = mid + 1; else r = mid, Ssgn = Nsgn;
} else {
char Asgn = lst == Ssgn ? '+' : '-', orig = now;
pb(l, mid), pb(mid + 1, r), Ssgn = reverse(Ssgn);
while ((now = query()) == orig);
if (Asgn == '+') l = mid + 1; else r = mid;
}
lst = now;
}
std::cout << "! " << l << std::endl;
}
其中