专栏文章
题解:P14099 [POCamp 2022] 一安在?2 / Where's Waldo?
P14099题解参与者 3已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mincm4b1
- 此快照首次捕获于
- 2025/12/02 00:13 3 个月前
- 此快照最后确认于
- 2025/12/02 00:13 3 个月前
这道题感觉没有黑的难度,可能是交互的知识点占比太高了吧。
做法
因为数据是纯随机的,所以说不会有像
1 10 9 8 7 6 5 4 3 2 的唐人数据,那么句考虑处理区间的平均数,平均数小的话那么出现 的概率就大,开一个优先队列,二分就可以了。因为平均数的原式是 ,会有精度损失,那么就考虑移项,变成 。询问的时候,我们在 中询问 ,那么 就是 。
那我们就开一个
CPPstruct 存储每一次查询,再开一个优先队列二分搜索。struct Node {
ll l, r, sum;
Node(ll l, ll r, ll sum) : l(l), r(r), sum(sum) {}
bool operator<(const Node &a) const {
return a.sum * (r - l + 1) < sum * (a.r - a.l + 1);
}
};
priority_queue<Node> q;
剪枝
剪枝一:如果这个区间的和 区间中所有可能的最大的数之和,显然 不在这里面(比如一个长度为 的区间的和 ,那么 肯定不在这里)。
剪枝二:如果当前区间 的值为 ,而 已经为另外一个点的坐标,那这样这个区间里也不存在 。就比如这个区间和为 ,但是 不在这个区间里,那么 也不在这个区间里了。
面向交互库编程
99 分代码
CPP// Problem: P14099 [POCamp 2022] 一安在?2 / Where's Waldo?
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P14099
// Memory Limit: 1024 MB
// Time Limit: 11000 ms
// Author: HoLuc1078
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a, b) memset(a, b, sizeof a)
#define M (N * 2)
using namespace std;
const int N = 1e5 + 10;
ll ask(ll l, ll r) {
cout << "? " << l << ' ' << r << '\n';
fflush(stdout);
ll x;
cin >> x;
return x;
}
struct Node {
ll l, r, sum;
Node(ll l, ll r, ll sum = 0) : l(l), r(r), sum(sum) {}
bool operator<(const Node &a) const {
return a.sum * (r - l + 1) < sum * (a.r - a.l + 1);
}
};
priority_queue<Node> q;
bool vis[N];
int main() {
ll T, n;
cin >> T >> n;
while (T--) {
mem(vis, 0);
while (!q.empty()) q.pop();
q.push(Node(1, n, ((n * (n + 1)) >> 1)));
while (!q.empty()) {
Node tmp = q.top();
q.pop();
ll l = tmp.l;
ll r = tmp.r;
ll sum = tmp.sum;
if (sum > ((n + n - r + l + 1) * (r - l) >> 1) + 1) continue;
if (r == l + 1 && vis[sum - 1]) continue;
ll mid = (l + r) >> 1;
ll x = ask(l, mid);
ll y = sum - x;
q.push(Node(l, mid, x));
q.push(Node(mid + 1, r, y));
if (l == mid) vis[x] = 1;
if (mid + 1 == r) vis[y] = 1;
if (l == mid && x == 1) {
cout << "! " << l << '\n';
fflush(stdout);
break;
}
if (mid + 1 == r && y == 1) {
cout << "! " << mid + 1 << '\n';
fflush(stdout);
break;
}
}
}
return 0;
}
注意
代码改进:
CPP //if (sum > ((n + n - r + l + 1) * (r - l) >> 1) + 1) continue;
if (l == r || (r == l + 1 && sum > n + 1)) continue;
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...