Problem p02648 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define FOR(i, a, b) for (int i = (a), i##_len = (b); i < i##_len; i++)
#define FORD(i, a, b) for (int i = (a), i##_len = (b); i > i##_len; i--)
#define ALL(x) (x).begin(), (x).end() // sortなどの引数を省略したい
#define MAX(x) *max_element(ALL(x))
#define MIN(x) *min_element(ALL(x))

int main() {
  int n, q;
  cin >> n;
  vector<tuple<int, int>> vw(n);
  REP(i, n) {
    int a, b;
    cin >> a >> b;
    vw[i] = make_tuple(a, b);
  }
  cin >> q;
  vector<tuple<int, int>> vl(q);
  REP(i, q) {
    int a, b;
    cin >> a >> b;
    vl[i] = make_tuple(a, b);
  }

  int former = min(4, n);
  vector<vector<int>> former_dp(former, vector<int>(100001, -1));
  vector<set<int>> former_set(former);

  former_dp[0][0] = 0;
  former_dp[0][get<1>(vw[0])] = get<0>(vw[0]);
  former_set[0].insert(0);
  former_set[0].insert(get<1>(vw[0]));

  FOR(i, 1, former) {
    int v, w;
    tie(v, w) = vw[i];
    auto &anc_dp = former_dp[(i - 1) / 2];
    auto &now_dp = former_dp[i];
    auto &anc_set = former_set[(i - 1) / 2];
    auto &now_set = former_set[i];
    for (auto j : anc_set) {
      now_dp[j] = anc_dp[j];
      now_set.insert(j);
    }
    for (auto j : anc_set) {
      if (w + j <= 100000) {
        now_dp[w + j] = max(now_dp[w + j], anc_dp[j] + v);
        now_set.insert(w + j);
      }
    }
  }

  REP(i, former) {
    int m = 0;
    auto &now_dp = former_dp[i];
    FOR(j, 1, 100001) {
      m = max(m, now_dp[j]);
      now_dp[j] = m;
    }
  }

  for (auto temp : vl) {
    int v, l;
    tie(v, l) = temp;
    if (v <= former) {
      cout << former_dp[v - 1][l] << endl;
      continue;
    }
    vector<tuple<int, int>> later;
    int vv = v;
    while (vv > former) {
      later.push_back(vw[vv - 1]);
      vv >>= 1;
    }
    auto &anc_dp = former_dp[vv - 1];
    int m = later.size();
    int ans = 0;
    REP(i, pow(2, m)) {
      int v_sum = 0;
      int w_sum = 0;
      int ii = i;
      for (auto temp : later) {
        int j, k;
        tie(j, k) = temp;
        if (ii & 1) {
          v_sum += j;
          w_sum += k;
        }
        ii >>= 1;
      }
      if (w_sum > l) {
        continue;
      }
      ans = max(ans, v_sum + anc_dp[l - w_sum]);
    }
    cout << ans << endl;
  }
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define FOR(i, a, b) for (int i = (a), i##_len = (b); i < i##_len; i++)
#define FORD(i, a, b) for (int i = (a), i##_len = (b); i > i##_len; i--)
#define ALL(x) (x).begin(), (x).end() // sortなどの引数を省略したい
#define MAX(x) *max_element(ALL(x))
#define MIN(x) *min_element(ALL(x))

int main() {
  int n, q;
  cin >> n;
  vector<tuple<int, int>> vw(n);
  REP(i, n) {
    int a, b;
    cin >> a >> b;
    vw[i] = make_tuple(a, b);
  }
  cin >> q;
  vector<tuple<int, int>> vl(q);
  REP(i, q) {
    int a, b;
    cin >> a >> b;
    vl[i] = make_tuple(a, b);
  }

  int former = min(512, n);
  vector<vector<int>> former_dp(former, vector<int>(100001, -1));
  vector<set<int>> former_set(former);

  former_dp[0][0] = 0;
  former_dp[0][get<1>(vw[0])] = get<0>(vw[0]);
  former_set[0].insert(0);
  former_set[0].insert(get<1>(vw[0]));

  FOR(i, 1, former) {
    int v, w;
    tie(v, w) = vw[i];
    auto &anc_dp = former_dp[(i - 1) / 2];
    auto &now_dp = former_dp[i];
    auto &anc_set = former_set[(i - 1) / 2];
    auto &now_set = former_set[i];
    for (auto j : anc_set) {
      now_dp[j] = anc_dp[j];
      now_set.insert(j);
    }
    for (auto j : anc_set) {
      if (w + j <= 100000) {
        now_dp[w + j] = max(now_dp[w + j], anc_dp[j] + v);
        now_set.insert(w + j);
      }
    }
  }

  REP(i, former) {
    int m = 0;
    auto &now_dp = former_dp[i];
    FOR(j, 1, 100001) {
      m = max(m, now_dp[j]);
      now_dp[j] = m;
    }
  }

  for (auto temp : vl) {
    int v, l;
    tie(v, l) = temp;
    if (v <= former) {
      cout << former_dp[v - 1][l] << endl;
      continue;
    }
    vector<tuple<int, int>> later;
    int vv = v;
    while (vv > former) {
      later.push_back(vw[vv - 1]);
      vv >>= 1;
    }
    auto &anc_dp = former_dp[vv - 1];
    int m = later.size();
    int ans = 0;
    REP(i, pow(2, m)) {
      int v_sum = 0;
      int w_sum = 0;
      int ii = i;
      for (auto temp : later) {
        int j, k;
        tie(j, k) = temp;
        if (ii & 1) {
          v_sum += j;
          w_sum += k;
        }
        ii >>= 1;
      }
      if (w_sum > l) {
        continue;
      }
      ans = max(ans, v_sum + anc_dp[l - w_sum]);
    }
    cout << ans << endl;
  }
}