AtCoder AISing Programming Contest 2019 Task D. Nearest Card Game

题目分析在代码注释里。

int main() {
#if defined LOCAL && !defined DUIPAI
  ifstream in("main.in");
  cin.rdbuf(in.rdbuf());
//  ofstream out("main.out");
//  cout.rdbuf(out.rdbuf());
#endif
  int n, q;
  scan(n, q);
  vi a(n);
  scan(a);
  vl sum(n);
  sum[0] = a[0];
  rng (i, 1, n) {
    sum[i] = a[i] + sum[i - 1];
  }
  vl parity_sum(n);
  parity_sum[0] = a[0];
  parity_sum[1] = a[1];
  rng (i, 2, n) {
    parity_sum[i] = a[i] + parity_sum[i - 2];
  }

  rep (q) {
    int x;
    scan(x);
    // 二分查找Aoki拿走的最大的数。
    // 设Aoki拿走的最大的数是a[i]。
    // 拿了a[i]之后,Aoki手里共有 i + 1 - LB(a, x - abs(x - a[i])) 个数。
    // 而此时Takahashi手里至多有n - i 个数,因此i必须满足i + 1 - LB(a, x - abs(x - a[i])) <= n - i
    int l = 0, r = n - 1;
    while (l + 1 < r) {
      bool flag = false;
      int mid = get_mid(l, r);
      int at_most = n - 1 - mid;
      auto t = LB(a, x - abs(x - a[mid]));
      int taken = mid - t + 1;
      if (taken <= at_most) {
        l = mid;
      } else {
        r = mid;
      }
    }
    ll ans = sum[n - 1] - sum[l];
    int num = n - 1 - l;
    if (n - 2 * num - 1 >= 0) {
      ans += parity_sum[n - 2 * num - 1];
    }
    println(ans);
  }
#if defined LOCAL && !defined DUIPAI
  cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
  return 0;
}
posted @ 2019-12-18 20:33  Pat  阅读(214)  评论(0编辑  收藏  举报