社区讨论

CF2163D 交互库实现

CF2163D2Diadrash (Hard Version)参与者 2已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mhz4bfsr
此快照首次捕获于
2025/11/15 01:14
4 个月前
此快照最后确认于
2025/11/16 13:50
4 个月前
查看原帖
使用 ChatGPT 5。
时间复杂度线性对数。已通过测试。
对于 CF2163D2 的测试,解除第一行注释即可。
输入格式为 Hack 数据格式。
请自备 testlib.h。适用于 CPH-NG。
CPP
// #define HD
#include <bits/stdc++.h>

#include "testlib.h"
using namespace std;

struct MexHelper {
  int n;
  vector<int> pos;      // pos[v] = index of value v in permutation (1-indexed)
  vector<int> prefMin;  // prefMin[m] = min pos[0..m-1]
  vector<int> prefMax;  // prefMax[m] = max pos[0..m-1]

  MexHelper() = default;
  MexHelper(int n_, const vector<int> &p1) { init(n_, p1); }

  void init(int n_, const vector<int> &p1) {
    n = n_;
    pos.assign(n, 0);
    for (int i = 1; i <= n; ++i) pos[p1[i]] = i;

    prefMin.assign(n + 1, n + 1);
    prefMax.assign(n + 1, 0);
    // m = 0: 空集,min=+inf, max=0,必满足任意 [l,r]
    for (int m = 1; m <= n; ++m) {
      int pv = pos[m - 1];
      prefMin[m] = min(prefMin[m - 1], pv);
      prefMax[m] = max(prefMax[m - 1], pv);
    }
  }

  // O(log n) mex on [l..r]
  int mexOnSubarray(int l, int r) const {
    int lo = 0, hi = n;  // 最大 m 使得所有 {0..m-1} 的 pos 都在 [l,r]
    while (lo < hi) {
      int mid = (lo + hi + 1) >> 1;
      if (prefMin[mid] >= l && prefMax[mid] <= r)
        lo = mid;
      else
        hi = mid - 1;
    }
    return lo;  // mex = lo
  }
};

// 计算“所有给定区间中 mex 的最大值”,O(n+q)
static int computeAnswer(int n, const vector<int> &p1,
                         const vector<pair<int, int>> &ranges) {
  // pos[v]
  vector<int> pos(n);
  for (int i = 1; i <= n; ++i) pos[p1[i]] = i;

  // mxR[L] = max_{l' <= L} r'
  vector<int> bestRByL(n + 1, -1);
  for (auto [l, r] : ranges) {
    bestRByL[l] = max(bestRByL[l], r);
  }
  vector<int> mxR(n + 1, -1);
  for (int L = 1; L <= n; ++L) mxR[L] = max(mxR[L - 1], bestRByL[L]);

  // 扩张包络 [L..R] 覆盖 {0..m-1}
  int L = n + 1, R = 0, ans = 0;
  for (int m = 1; m <= n; ++m) {
    int posNew = pos[m - 1];
    L = min(L, posNew);
    R = max(R, posNew);
    if (mxR[L] >= R)
      ans = m;
    else
      break;
  }
  return ans;  // 若存在覆盖全体的区间,答案可达 n
}

int main(int argc, char *argv[]) {
  registerInteraction(argc, argv);

  int T = inf.readInt(1, 100, "t");
  cout << T << endl;  // flush

  long long totalQueries = 0;

  for (int tc = 1; tc <= T; ++tc) {
    int n = inf.readInt(4, 10000, "n");
    int q = inf.readInt(1, 300000, "q");
    int MAX_Q = std::max(300, (int)ceil(n / 2.0) + 2);
#ifdef HD
    MAX_Q = 30;
#endif
    // 读 permutation(1-indexed)
    vector<int> p1(n + 1);
    vector<int> seen(n, 0);
    for (int i = 1; i <= n; ++i) {
      int v = inf.readInt(0, n - 1, "p_i");
      if (seen[v]) quitf(_fail, "Input permutation contains duplicates.");
      seen[v] = 1;
      p1[i] = v;
    }
    for (int v = 0; v < n; ++v) {
      if (!seen[v]) quitf(_fail, "Input permutation is missing value %d.", v);
    }

    vector<pair<int, int>> ranges(q);
    for (int i = 0; i < q; ++i) {
      int l = inf.readInt(1, n, "l_i");
      int r = inf.readInt(l, n, "r_i");
      ranges[i] = {l, r};
    }

    // 输出给选手:n q 和所有区间
    cout << n << ' ' << q << endl;
    for (auto [l, r] : ranges) cout << l << ' ' << r << endl;

    // 预处理:O(n) 构建 mex 查询助手(O(log n) 查询)
    MexHelper mexer(n, p1);

    // 正确答案:O(n+q)
    int correct = computeAnswer(n, p1, ranges);

    int queriesUsed = 0;
    while (true) {
      // 注意:不要把提示语当作正则;这里读一个“词”
      string op = ouf.readWord();

      if (op == "?") {
        int l = ouf.readInt(1, n, "l");
        int r = ouf.readInt(l, n, "r");

        ++queriesUsed;
        ++totalQueries;
        if (queriesUsed > MAX_Q) {
          quitf(_wa, "Too many queries in test #%d: %d used (limit %d).", tc,
                queriesUsed, MAX_Q);
        }

        int mex = mexer.mexOnSubarray(l, r);  // O(log n)
        cout << mex << endl;                  // flush
      } else if (op == "!") {
        int x = ouf.readInt(0, n, "answer");
        if (x != correct) {
          quitf(_wa, "Wrong answer on test #%d: got %d, expected %d.", tc, x,
                correct);
        }
        break;  // 进入下一组
      } else {
        quitf(_wa, "Unknown token '%s'. Expected '?' or '!'.", op.c_str());
      }
    }
  }

  quitf(_ok, "Accepted. Total queries used: %lld.", totalQueries);
  return 0;
}
样例数据:
PLAINTEXT
3
4 3
0 3 1 2
1 2
2 4
1 3
6 6
3 5 0 1 4 2
1 2
2 4
3 3
4 6
5 5
6 6
4 4
0 1 2 3
1 1
2 2
3 3
4 4

回复

1 条回复,欢迎继续交流。

正在加载回复...