[gym 101149 M. Ex Machina]构造+线段树
分类:Data Structure
SegMent Tree
Construction
1. 题目链接
[gym 101149 M. Ex Machina]构造+线段树
2. 题意描述
交互题。有
n
个互不相同的数,要你通过
3. 解题思路
比较有意思的一道构造题。题目要求用
n+log(n)
次询问求出次大数的位置。
按照线段树来比较大小,用节点记录,子树的最大值所在的位置。叶子节点有
n
个,那么非叶子节点就是
然后,根据求出的最大数所在位置,求出了从根节点到该叶子节点的一条路径,这个路径上最多
log(n)
个节点。那么,次大值肯定是该路径某个节点的儿子。那么再来
log(n)
次查询,就知道了次大数所在的位置了。
4. 实现代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double lb;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> puu;
typedef pair<lb, lb> pbb;
typedef vector<int> vi;
typedef tuple<int, int, int> iii;
const int INF = 0x3f3f3f3f;
const ll INFL = 0x3f3f3f3f3f3f3f3fLL;
template<typename T> inline void umax(T &a, T b) { a = max(a, b); }
template<typename T> inline void umin(T &a, T b) { a = min(a, b); }
template<typename T> inline T randIntv(const T& a, const T& b) { return (T)rand() % (b - a + 1) + a; }
void debug() { cout << endl; }
template<typename T, typename ...R> void debug (T f, R ...r) { cout << "[" << f << "]"; debug (r...); }
const int MAXN = 1005;
int n, seg[MAXN << 2];
namespace Interaction {
int times;
#ifdef ___LOCAL_WONZY___
int rank[MAXN];
#endif
void init() {
times = n + 24;
#ifdef ___LOCAL_WONZY___
for (int i = 1; i <= n; ++i) rank[i] = i;
random_shuffle(rank + 1, rank + n + 1);
for (int i = 1; i <= n; ++i) printf("[%d]", rank[i]);
printf("\n");
#endif
}
#ifdef ___LOCAL_WONZY___
int ask(int a, int b) {
-- times;
if (rank[a] == rank[b]) return 0;
return (rank[a] < rank[b]) ? -1 : 1;
}
#else
char buf[10];
int ask(int a, int b) {
-- times;
printf("? %d %d\n", a, b);
fflush(stdout);
scanf("%s", buf);
if (buf[0] == '=') return 0;
return (buf[0] == '<') ? -1 : 1;
}
#endif // ___LOCAL_WONZY___
}
#define lch (rt << 1)
#define rch (rt << 1 | 1)
#define lson l, md, lch
#define rson md + 1, r, rch
int idx[MAXN], tot;
void build(int l, int r, int rt) {
if (l == r) {
seg[rt] = idx[l];
return;
}
int md = (l + r) >> 1;
build(lson);
build(rson);
int a = seg[lch], b = seg[rch];
int ret = Interaction::ask(a, b);
assert(ret != 0);
seg[rt] = ret == 1 ? a : b;
}
void dfs(int l, int r, int rt) {
if (l == r) return;
int md = (l + r) >> 1;
if (seg[rt] == seg[lch]) {
idx[++ tot] = seg[rch];
dfs(lson);
} else {
idx[++ tot] = seg[lch];
dfs(rson);
}
}
int main() {
#ifdef ___LOCAL_WONZY___
freopen("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
scanf("%d", &n);
Interaction::init();
for (int i = 1; i <= n; ++i) idx[i] = i;
build(1, n, 1);
// debug(seg[1]);
tot = 0;
dfs(1, n, 1);
build(1, tot, 1);
// debug(seg[1]);
printf("! %d\n", seg[1]);
assert(Interaction::times > 0);
#ifdef ___LOCAL_WONZY___
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << "ms." << endl;
#endif // ___LOCAL_WONZY___
return 0;
}