luogu P7004 [NEERC2013]Interactive Interception 题解
感觉比较玄学的交互,看了题解才会做。
主体的思想是,我们在二分位置的同时也对 \(v\) 的范围进行修改。
假设我们现在的区间是 \([L,R]\) ,那么我们取 \(mid=\frac{L+R}{2}\) ,然后再询问 \(check(L, mid)\) 。
这样可以先得到当前时间上点 \(P\) 所在位置的范围,并把范围记录下来。
接着我们枚举每一个之前我们记录下来的位置范围 \(l_i\) 到 \(r_i\) 。
然后结合当前的 \(L\) 和 \(R\) 计算题目中速度的范围,再模拟让点再向前走一步即可。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cctype>
#include <string>
#define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
using std::pair;
using std::make_pair;
using std::string;
#define pii pair<int, int>
#define mp make_pair
using ll = long long;
const int inf = 1e9;
const ll infll = 0ll + 1e18;
#define int long long
const int N = 505;
int pos, v, mxv, l[N], r[N], tot, vleft, vright;
inline int check(int l, int r) {
std::cout << "check " << l << " " << r << std::endl;
string res; std::cin >> res;
if (res[0] == 'Y') return 1;
else return 0;
}
signed main(void) {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL), std::cout.tie(NULL);
std::cin >> pos >> vright;
int left = 0, right = pos;
while (left < right) {
int mid = (left + right) / 2;
if (check(left, mid) == 1) right = mid;
else left = mid + 1;
for (int i = 1; i <= tot; i ++) {
vleft = std::max(vleft, (left - r[i]) / (tot + 1 - i));
vright = std::min(vright, (right - l[i]) / (tot + 1 - i));
}
tot ++;
l[tot] = left, r[tot] = right;
left += vleft;
right += vright;
}
std::cout << "answer " << left << std::endl;
return 0;
}