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

#include <bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 100005

struct Info {
  ll cost, value;
};

struct Data {
  ll base, limit;
};

int N, M;
Info info[NUM];
Data data[NUM];

int main() {

  scanf("%d %d", &N, &M);

  for (int i = 0; i < N; i++) {

    scanf("%lld %lld", &info[i].cost, &info[i].value);
  }

  int index = 0;
  ll tmp_base, tmp_limit, pre_base = -1;

  for (int i = 0; i < M; i++) {

    scanf("%lld %lld", &tmp_base, &tmp_limit);
    if (tmp_base == pre_base) {

      data[index - 1].limit =
          min(data[index - 1].limit, tmp_limit); // 一番制約がきついものを残す
    } else {

      data[index].base = tmp_base;
      data[index].limit = tmp_limit;

      index++;
    }
  }

  M = index;

  data[M].base = BIG_NUM;
  data[M].limit = BIG_NUM;

  ll ans = 0;
  priority_queue<ll> Q, TMP;

  // 最小制約より小さいものは解に計上
  for (index = 0; index < N && info[index].cost < data[0].base; index++) {

    ans += info[index].value;
  }

  int current_limit = BIG_NUM;

  for (int i = 0; i < M; i++) {

    if (current_limit >
        data[i]
            .limit) { // 制約が厳しくなるなら、既に条件を満たしているものを解に計上

      if (current_limit != BIG_NUM) {

        for (int k = 0;
             k < (current_limit - data[i].limit) && Q.empty() == false; k++) {

          ans += Q.top();
          Q.pop();
        }
      }
      current_limit = data[i].limit;
    }

    // data[i].base <= info[index].cost < data[i+1].baseとなるものをPQにpush
    for (; index < N && data[i].base <= info[index].cost &&
           info[index].cost < data[i + 1].base;
         index++) {

      Q.push(info[index].value);
    }
  }

  for (int i = 0; i < current_limit - 1 && Q.empty() == false; i++) {

    ans += Q.top();
    Q.pop();
  }

  printf("%lld\\n", ans);

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 100005

struct Info {
  ll cost, value;
};

struct Data {
  ll base, limit;
};

int N, M;
Info info[NUM];
Data data[NUM];

int main() {

  scanf("%d %d", &N, &M);

  for (int i = 0; i < N; i++) {

    scanf("%lld %lld", &info[i].cost, &info[i].value);
  }

  int index = 0;
  ll tmp_base, tmp_limit, pre_base = -1;

  for (int i = 0; i < M; i++) {

    scanf("%lld %lld", &tmp_base, &tmp_limit);
    if (tmp_base == pre_base) {

      data[index - 1].limit =
          min(data[index - 1].limit, tmp_limit); // 一番制約がきついものを残す
    } else {

      data[index].base = tmp_base;
      data[index].limit = tmp_limit;

      index++;
    }
  }

  M = index;

  data[M].base = BIG_NUM;
  data[M].limit = 0;

  ll ans = 0;
  priority_queue<ll> Q, TMP;

  int left, right, mid, pre_index = N, min_index, max_index;

  for (int i = M - 1; i >= 0; i--) { // 制約を降順に走査する

    max_index = pre_index - 1; // 新しくPQにpushする区間の右端

    // 2分探索で、data[i].base以上の値段を持つinfoの最小のindexを求める
    min_index = N;
    left = 0, right = max_index, mid = (left + right) / 2;

    while (left <= right) {

      if (info[mid].cost >= data[i].base) {

        min_index = mid;
        right = mid - 1;

      } else {

        left = mid + 1;
      }
      mid = (left + right) / 2;
    }

    if (min_index == N)
      continue; // 制約以上の値段を持つ菓子がない

    for (int k = min_index; k <= max_index; k++) {

      Q.push(info[k].value); // 美味しさをPQにpush
    }

    for (int k = 0; k < data[i].limit - 1 && Q.empty() == false;
         k++) { // 最大でdata[i].limit-1個残す

      TMP.push(Q.top());
      Q.pop();
    }
    while (!Q.empty()) {
      Q.pop();
    }
    while (!TMP.empty()) {
      Q.push(TMP.top());
      TMP.pop();
    }

    pre_index = min_index;
    if (pre_index == 0)
      break;
  }

  while (!Q.empty()) {

    ans += Q.top();
    Q.pop();
  }

  // 最小制約より小さいお菓子は無条件で追加
  for (int i = pre_index - 1; i >= 0; i--) {

    ans += info[i].value;
  }

  printf("%lld\\n", ans);

  return 0;
}