Problem p02648 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>

using namespace std;

const int max_n = 300333, inf = 1000111222;
const int max_b = 9;
const int max_mask = (1 << max_b) + 5;

int n, q, a[max_n], b[max_n];
vector<pair<int, int>> all, all1, all2;
pair<int, int> sum[2][max_mask];
pair<int, int> buf[max_mask];

void get_all(const vector<pair<int, int>> &all, pair<int, int> sum[]) {
  for (int i = 0; i < all.size(); ++i) {
    for (int j = 0; j < (1 << i); ++j) {
      sum[(1 << i) + j] = sum[j];
      sum[(1 << i) + j].first += all[i].first;
      sum[(1 << i) + j].second += all[i].second;
    }
    merge(sum, sum + (1 << i), sum + (1 << i), sum + (1 << (i + 1)), buf);
    copy(buf, buf + (1 << (i + 1)), sum);
  }
}

const bool debug = 0;

mt19937 generator(1);

int rnd() { return generator() >> 1; }

int rnd(int r) { return rnd() % r; }

int rnd(int l, int r) { return l + rnd(r - l + 1); }

int main() {
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
  if (debug) {
    n = (1 << 18) - 1;
    for (int i = 1; i <= n; ++i) {
      a[i] = rnd(100000);
      b[i] = rnd(100000);
    }
    q = 100000;
  } else {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
      scanf("%d%d", &a[i], &b[i]);
    }
    scanf("%d", &q);
  }
  while (q--) {
    int v, mx;
    if (debug) {
      v = rnd(n / 2 + 2, n);
      mx = 100000;
    } else {
      scanf("%d%d", &v, &mx);
    }
    all.clear();
    all1.clear();
    all2.clear();
    while (v) {
      all.push_back({b[v], a[v]});
      v /= 2;
    }
    const int sz1 = min(9, (int)all.size() / 2);
    const int sz2 = all.size() - sz1;
    for (int i = 0; i < sz1; ++i) {
      all1.push_back(all[i]);
    }
    for (int i = sz1; i < all.size(); ++i) {
      all2.push_back(all[i]);
    }
    get_all(all1, sum[0]);
    get_all(all2, sum[1]);
    for (int i = 1; i < (1 << sz1); ++i) {
      sum[0][i].second = max(sum[0][i].second, sum[0][i - 1].second);
    }
    int ans = 0, pos = (1 << sz1) - 1;
    for (int i = 0; i < (1 << sz2) && sum[1][i].first <= mx; ++i) {
      while (sum[1][i].first + sum[0][pos].first > mx) {
        --pos;
      }
      ans = max(ans, sum[1][i].second + sum[0][pos].second);
    }
    printf("%d\\n", ans);
  }
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

const int max_n = 300333, inf = 1000111222;
const int max_b = 9;
const int max_mask = (1 << max_b) + 5;

int n, q, a[max_n], b[max_n];
vector<pair<int, int>> all, all1, all2;
pair<int, int> sum[2][max_mask];

void get_all(const vector<pair<int, int>> &all, pair<int, int> sum[]) {
  for (int mask = 1; mask < (1 << all.size()); ++mask) {
    int id = __builtin_ctz(mask);
    sum[mask] = sum[mask ^ (1 << id)];
    sum[mask].first += all[id].first;
    sum[mask].second += all[id].second;
  }
}

const bool debug = 0;

mt19937 generator(1);

int rnd() { return generator() >> 1; }

int rnd(int r) { return rnd() % r; }

int rnd(int l, int r) { return l + rnd(r - l + 1); }

int main() {
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
  if (debug) {
    n = (1 << 18) - 1;
    for (int i = 1; i <= n; ++i) {
      a[i] = rnd(100000);
      b[i] = rnd(100000);
    }
    q = 100000;
  } else {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
      scanf("%d%d", &a[i], &b[i]);
    }
    scanf("%d", &q);
  }
  while (q--) {
    int v, mx;
    if (debug) {
      v = rnd(n / 2 + 2, n);
      mx = 100000;
    } else {
      scanf("%d%d", &v, &mx);
    }
    all.clear();
    all1.clear();
    all2.clear();
    while (v) {
      all.push_back({b[v], a[v]});
      v /= 2;
    }
    const int sz1 = min(9, (int)all.size() / 2);
    const int sz2 = all.size() - sz1;
    for (int i = 0; i < sz1; ++i) {
      all1.push_back(all[i]);
    }
    for (int i = sz1; i < all.size(); ++i) {
      all2.push_back(all[i]);
    }
    get_all(all1, sum[0]);
    get_all(all2, sum[1]);
    sort(sum[0], sum[0] + (1 << sz1));
    for (int i = 1; i < (1 << sz1); ++i) {
      sum[0][i].second = max(sum[0][i].second, sum[0][i - 1].second);
    }
    int ans = 0;
    for (int i = 0; i < (1 << sz2); ++i) {
      if (sum[1][i].first <= mx) {
        int pos = upper_bound(sum[0], sum[0] + (1 << sz1),
                              make_pair(mx - sum[1][i].first, inf)) -
                  sum[0] - 1;
        ans = max(ans, sum[1][i].second + sum[0][pos].second);
      }
    }
    printf("%d\\n", ans);
  }
  return 0;
}