跳转至

Atcoder ABC 457

Info

2026.04.25 第十周 周六 链接

这把ab做完C写了一堆很丑的上去,wa了一发以后就摆了(,把CD补一下吧

A 签到

B 签到

void solve() {
  int n;
  cin >> n;
  auto a = vector(n, deque<int>());
  for (int i = 0; i < n; i ++) {
    int l;
    cin >> l;
    for (int j = 0; j < l; j ++) {
      int xx;
      cin >> xx;
      a[i].push_back(xx);
    }
  }
  int x, y;
  cin >> x >> y;
  x --, y --;
  cout << a[x][y] << endl;
}

C

题目:创造出一个新数组\(B\),就是把\(A\)的第\(i\)个数组重复\(C_i\)次,然后找到\(B\)的第\(k\)个元素

input

\(n\ k\)

\(l_1\ A_{1,1} \cdots\ A_{1,L_1}\)

\(.\)

\(.\)

\(l_N\ A_{N,1} \cdots\ A_{N,L_N}\)

\(C_1\ C_2\ \cdots \ C_N\)

Tip

首先,把\(B\)给构造出来一定是没必要的

唉就是一个个块查过去就好了

void solve2() {
  int n;
  i64 k;
  cin >> n >> k;
  vector<vector<int>> a(n + 1);
  vector<int> len(n + 1);
  for (int i = 1; i <= n; i ++) {
    cin >> len[i];
    a[i].resize(len[i] + 1);
    for (int j = 1; j <= len[i]; j ++) {
      cin >> a[i][j];
    }
  }

  vector<int> c(n + 1);
  for (int i = 1; i <= n; i ++) cin >> c[i];
  for (int i = 1; i <= n; i ++) {
    i64 block = (i64)c[i] * len[i];
    if (k > block) {
      k -= block;
    } else {
      k = (k - 1) % len[i];
      cout << a[i][k + 1];
      return;
    }
  }
}

D 二分

最大值最小

二分信号,考试的时候一开始想的是贪心(

k的范围也是到了\(10^{18}\),确实应该想到二分,太久没遇到二分了

二分答案啊

单独验证一个答案稍微有点复杂的时候就容易想不到

其实这个答案验证就是\(O(n)\)

呃呃啊啊

void solve() {
  int n;
  i64 k;
  cin >> n >> k;
  vector<i64> a(n + 1);
  for (int i = 1; i <= n; i ++) cin >> a[i];

  auto check = [&](i64 x) {
    i64 need = 0;
    for (int i = 1; i <= n; i ++) {
      if (a[i] < x) {
        i64 diff = x - a[i];
        need += (diff + i - 1)  / i;
        if (need > k) return false;
      }
    }
    return true;
  };

  i64 lo = 0, hi = 4e18;
  while (lo <= hi) {
    i64 mid = (lo + hi) / 2;
    if (check(mid)) lo = mid + 1;
    else hi = mid - 1;
  }
  cout << hi << endl;
}