• WC2019 I 君的商店


    交互题

    一个 01 序列,告诉你其中 1 有奇数个还是偶数个,每次可以给定两个集合 $A$,$B$,系统会告诉你 $A leq B$ 或者 $B leq A$

    求序列

    交互次数要求 $5n + O(log_2 n)$

    有一个 subtask 满足原序列是一条从不上升或者不下降的链,要求 $O(log_2n)$

    sol:

    首先有一个交互次数 $2n + 5n$ 的做法:首先 $2n$ 次找出最大值,最大的那个肯定是 $1$,之后每次问两个还不确定的($a,b$),$a+b$ 是否大于等于 $1$

    如果大于等于,那么 $a,b$ 中较大的是 $1$,否则 $a,b$ 中较小的是 $0$。最后特判一下奇偶性不符的情况即可

    然后对于一条链的情况,首先,两个端点一定有一个 1,二分找出一个位置最小的 $x$ 使得 $p[x] + p[x+1] geq 1$ 即可

    分界线那里用奇偶性特判一下 $O(log_2n)$

    正解

    发现 5n 的部分不太好优化,考虑一边 5n 一边确定一个递增的关系,然后用 logn 次确定那条链

    具体地,可以从三个数 $(x,y,z)$ 开始,先比较 $x,y$,不妨设大的那个是 $y$

    如果 $x+y leq z$,则 $x=0$,再找一个 $x$

    否则 $y geq z$,把 $y$ 放到 $z$ 的位置,再找一个 $y$

    这样会确定若干个 $0$ ,剩一个比不出去的,和一条递增的链

    容易知道比不出去的和链最大值中较大的那个是 $1$,可以直接上二分

    二分之后还有一个不确定的分界线和一个比不出去的,$O(1)$ 讨论一下即可

    #include <bits/stdc++.h>
    #include "shop.h"
    #define LL long long
    #define rep(i, s, t) for (register int i = s, i##end = t; i <= i##end; ++i)
    #define dwn(i, s, t) for (register int i = s, i##end = t; i >= i##end; --i)
    using namespace std;
    int arr[5], brr[5];
    int ans[100010], que[100010], chain[100010];
    int ask(int x, int y) {
        arr[0] = x, brr[0] = y;
        return query(arr, 1, brr, 1);
    }
    int ask2(int x, int fst, int scd) {
        arr[0] = x, brr[0] = fst, brr[1] = scd;
        return query(arr, 1, brr, 2);
    }
    void find_price(int task_id, int N, int K, int ans[]) {
        auto solvechain = [&](int N, int K) {
            int l = 0, r = N - 2, res = N - 1;
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (ask2(que[N - 1], que[mid], que[mid + 1]))
                    res = mid, r = mid - 1;
                else
                    l = mid + 1;
            }
            int val = res;
            if (K != ((N - res) & 1))
                res++;
            rep(i, 0, res - 1) ans[que[i]] = 0;
            rep(i, res, N - 1) ans[que[i]] = 1;
            return val;
        };
        for (int i = 0; i < N; ++i) ans[i] = 0;
        if (task_id == 3) {
            for (int i = 0; i < N; ++i) que[i] = i;
            if (ask(N - 1, 0))
                reverse(que, que + N);
            solvechain(N, K);
        } else if (task_id == 6) {
            if (N == 1)
                ans[0] = 1;
            else if (N == 2) {
                int mx = ask(0, 1) ? 1 : 0;
                ans[mx] = 1;
                if (!K)
                    ans[!mx] = 1;
            } else {
                int dfn = N - 1, cd = 1;
                chain[0] = 0;
                for (int i = 1; i < N; ++i) que[i] = i;
                while (dfn > 1) {
                    if (!ask2(chain[cd - 1], que[dfn], que[dfn - 1])) {
                        if (!ask(que[dfn], que[dfn - 1]))
                            swap(que[dfn], que[dfn - 1]);
                        ans[que[dfn]] = 0;
                    } else {
                        if (ask(que[dfn], que[dfn - 1]))
                            swap(que[dfn], que[dfn - 1]);
                        chain[cd++] = que[dfn];
                    }
                    dfn--;
                }
                if (ask(que[dfn], chain[cd - 1])) {
                    ans[chain[cd - 1]] = 1;
                    int cmx = que[dfn];
                    dfn = cd;
                    for (int i = 0; i < cd; ++i) que[i] = chain[i];
                    int cur = solvechain(dfn, K);
                    K ^= ((dfn - cur - 1) & 1);
                    cur = que[cur];
                    if (!ask2(chain[cd - 1], cmx, cur)) {
                        if (ask(cmx, cur))
                            ans[cmx] = 0;
                        else
                            ans[cur] = 0;
                    } else {
                        if (ask(cur, cmx))
                            ans[cmx] = 1;
                        else
                            ans[cur] = 1;
                        K ^= 1;
                    }
                    ans[cmx] = K;
                } else {
                    ans[que[dfn]] = 1;
                    chain[cd++] = que[dfn];
                    for (int i = 0; i < cd; ++i) que[i] = chain[i];
                    solvechain(cd, K);
                }
            }
        } else {
            int mx = 0;
            for (int i = 1; i < N; ++i)
                if (ask(mx, i) == 1)
                    mx = i;
            ans[mx] = 1;
            int dfn = 0;
            K ^= 1;
            for (int i = 0; i < N; ++i) {
                if (i == mx)
                    continue;
                que[++dfn] = i;
            }
            while (dfn > 1) {
                if (ask2(mx, que[dfn], que[dfn - 1]) == 0) {
                    if (ask(que[dfn - 1], que[dfn]))
                        swap(que[dfn - 1], que[dfn]);
                    ans[que[dfn]] = 0;
                } else {
                    if (!ask(que[dfn - 1], que[dfn]))
                        swap(que[dfn - 1], que[dfn]);
                    ans[que[dfn]] = 1;
                    K ^= 1;
                }
                dfn--;
            }
            if (K && dfn)
                ans[que[dfn]] = 1;
        }
    }
    View Code
  • 相关阅读:
    vue Can't resolve 图片
    TP-LINK WR740N中继设置,AP设置,设置后不能上网,亲测有效
    vue VSCode 开发设置(html自动补全、eslint保存时格式化、vetur 格式化html)
    不再手写import
    vscode vuter的快捷键 关键字
    prototype是什么?
    真有效值与有效值概念
    现代文经典
    古文经典
    最后,我想对你说一句:我爱你
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10439327.html
Copyright © 2020-2023  润新知