[gym 101149 M. Ex Machina]构造+线段树

来源:互联网 发布:林智妍整容 知乎 编辑:程序博客网 时间:2024/06/04 18:43

[gym 101149 M. Ex Machina]构造+线段树

分类:Data Structure SegMent Tree Construction

1. 题目链接

[gym 101149 M. Ex Machina]构造+线段树

2. 题意描述

交互题。有n个互不相同的数,要你通过n+24次询问,确定那个数是次大数的位置。(1n1000)

3. 解题思路

比较有意思的一道构造题。题目要求用n+log(n)次询问求出次大数的位置。
按照线段树来比较大小,用节点记录,子树的最大值所在的位置。叶子节点有n个,那么非叶子节点就是n1个,每个非叶子节点都是查询,那么n1次查询就可以找到最大数所在位置。
然后,根据求出的最大数所在位置,求出了从根节点到该叶子节点的一条路径,这个路径上最多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];#endifvoid 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;}#elsechar 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, rchint 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;}