• CF1586D. Omkar and the Meaning of Life 题解 纪念一下第一道AC的交互题


    题目链接:https://codeforces.com/contest/1586/problem/D

    题目大意:

    有一个 \(1 \sim n\) 的排列 \(p\),你最多询问 \(2n\) 轮,每轮你可以输入一个长度为 \(n\) 的数列 \(a\),要求 \(1 \le a_i \le n\)(但 \(a\) 不需要是一个 \(1 \sim n\) 的排列)。

    对于你每次输入的数列 \(a\),程序会产生一个数列 \(s\),其中 \(s_i = p_i + a_i\),然后程序会返回给你一个出现过至少两次的 \(s_k\) 对应的最小坐标 \(k\)。若没有这个坐标 \(k\) 则返回 \(0\)

    要求在不超过 \(2n\) 轮求出原始的数列 \(p\)

    解题思路:

    \(p(1 \le p \le n)\) 轮共两次询问:

    • 第一次询问,除了 \(a_p = 2\) 以外,其他所有 \(a_i = 1\),设程序返回的整数是 \(q_1\),则:若 \(q_1 \neq 0\)\(q_1 \neq p\),说明第 \(p\) 个位置上面的数比第 \(q_1\) 个位置上面的数小 \(1\),则从 \(p\) 指向 \(q_1\) 一条边(\(p \rightarrow q_1\));
    • 第二次询问,除了 \(a_p = 1\) 以外,其他所有 \(a_i = 2\),设程序返回的整数是 \(q_2\),则:若 \(q_2 \neq 0\)\(q_2 \neq p\),说明第 \(p\) 个位置上面的数比第 \(q_1\) 个位置上面的数大 \(1\),则从 \(q-2\) 指向 \(p\) 一条边(\(q_2 \rightarrow p\))。

    然后这 \(2n\) 轮操作之后会发现 —— 形成了一条链,根据链还原出每个数的位置即可。

    示例程序:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 110;
    bool in[maxn];
    int n, q1, q2, g[maxn], x;
    
    void ask1(int p) {
        printf("?");
        for (int i = 1; i <= n; i ++) printf(" %d", (i == p) ? 2 : 1);
        puts("");
        fflush(stdout);
    }
    
    void ask2(int p) {
        printf("?");
        for (int i = 1; i <= n; i ++) printf(" %d", (i == p) ? 1 : 2);
        puts("");
        fflush(stdout);
    }
    
    int val[maxn];
    bool vis[maxn];
    
    int main() {
        scanf("%d", &n);
        for (int p = 1; p <= n; p ++) {
            ask1(p);
            scanf("%d", &q1);
            if (q1 != 0 && q1 != p) {
                g[p] = q1;
            }
            ask2(p);
            scanf("%d", &q2);
            if (q2 != 0 && q2 != p) {
                g[q2] = p;
            }
        }
        for (int i = 1; i <= n; i ++) {
            if (!g[i]) x = i;
        }
        for (int i = 1; i <= n; i ++) vis[ g[i] ] = true;
        for (int i = 1; i <= n; i ++) if (!vis[i]) { x = i; break; }
        for (int i = 1; i <= n; i ++) {
            val[x] = i;
            x = g[x];
        }
        printf("!");
        for (int i = 1; i <= n; i ++) printf(" %d", val[i]);
        return 0;
    }
    
  • 相关阅读:
    泛型
    Java反射及注解
    Java之线程与进程
    线程池
    HashMap、ConcurrentHashMap解析
    基于Opentracing+Jaeger全链路灰度调用链(转载)
    SpringBoot 开发案例之参数传递的正确姿势
    以np.concatenate为主题,谈谈numpy数组按维度合并的问题
    为什么阿里巴巴Java开发手册中强制要求整型包装类对象值用 equals 方法比较?
    [C++面试题]之字符串(转)
  • 原文地址:https://www.cnblogs.com/quanjun/p/15418227.html
Copyright © 2020-2023  润新知