Problem p03019 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 100010
#define int long long
char getc() {
  char c = getchar();
  while ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && (c < '0' || c > '9'))
    c = getchar();
  return c;
}
int gcd(int n, int m) { return m == 0 ? n : gcd(m, n % m); }
int read() {
  int x = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-')
      f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9')
    x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
  return x * f;
}
int n, m, pos;
ll ans, s[N], tot;
struct data {
  int x, l, r;
  bool operator<(const data &a) const {
    return 1ll * (m - x) * r + 1ll * x * l >
           1ll * (m - a.x) * a.r + 1ll * a.x * a.l;
  }
} a[N];
ll mxval(int i) { return 1ll * (m - a[i].x) * a[i].r; }
ll val(int i, int k) {
  if (k < a[i].x)
    return 1ll * (k - a[i].x) * a[i].l;
  else
    return 1ll * (k - a[i].x) * a[i].r;
}
bool check(int k, ll tot) {
  for (int i = 1; i < pos; i++)
    if (tot - mxval(i) + val(i, k) >= 0)
      return 1;
  tot -= mxval(pos);
  tot += val(pos, 0);
  for (int i = pos; i <= n; i++)
    if (tot - val(i, 0) + val(i, k) >= 0)
      return 1;
  return 0;
}
signed main() {
  freopen("c.in", "r", stdin);
  freopen("c.out", "w", stdout);
  n = read(), m = read();
  for (int i = 1; i <= n; i++)
    a[i].x = read(), a[i].l = read(), a[i].r = read();
  sort(a + 1, a + n + 1);
  for (int i = n; i >= 1; i--)
    s[i] = s[i + 1] - val(i, 0);
  tot = 0;
  pos = 0;
  for (int i = 1; i <= n; i++) {
    tot += mxval(i);
    if (tot >= s[i + 1]) {
      pos = i;
      break;
    }
  }
  if (pos == 0) {
    cout << 0;
    return 0;
  }
  tot -= s[pos + 1];
  int l = 0, r = m;
  while (l <= r) {
    int mid = l + r >> 1;
    if (check(mid, tot))
      ans = mid, r = mid - 1;
    else
      l = mid + 1;
  }
  cout << ans + 1ll * (pos - 1) * m;
  return 0;
  // NOTICE LONG LONG!!!!!
}
// 当权值确定后，显然优先学权值大的
// 一门课学的比对方多就使重要性取max，否则取min
// 既然已经点的比对方多，不如学满
// 该门课学满的收益为(m-x)*r 不学的减益为x*l 总价值为(m-x)*r+x*l
// 按该价值排序依次选完
// 至多只有一门课是不学满(若优则设为r否则设为l)的，其他要么不学(设为l)要么学满（设为r)
// 考虑哪一门不学满 不学满后应二分答案考虑是否可行

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 100010
#define int long long
char getc() {
  char c = getchar();
  while ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && (c < '0' || c > '9'))
    c = getchar();
  return c;
}
int gcd(int n, int m) { return m == 0 ? n : gcd(m, n % m); }
int read() {
  int x = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-')
      f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9')
    x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
  return x * f;
}
int n, m, pos;
ll ans, s[N], tot;
struct data {
  int x, l, r;
  bool operator<(const data &a) const {
    return 1ll * (m - x) * r + 1ll * x * l >
           1ll * (m - a.x) * a.r + 1ll * a.x * a.l;
  }
} a[N];
ll mxval(int i) { return 1ll * (m - a[i].x) * a[i].r; }
ll val(int i, int k) {
  if (k < a[i].x)
    return 1ll * (k - a[i].x) * a[i].l;
  else
    return 1ll * (k - a[i].x) * a[i].r;
}
bool check(int k, ll tot) {
  for (int i = 1; i < pos; i++)
    if (tot - mxval(i) + val(i, k) >= 0)
      return 1;
  tot -= mxval(pos);
  tot += val(pos, 0);
  for (int i = pos; i <= n; i++)
    if (tot - val(i, 0) + val(i, k) >= 0)
      return 1;
  return 0;
}
signed main() {
  n = read(), m = read();
  for (int i = 1; i <= n; i++)
    a[i].x = read(), a[i].l = read(), a[i].r = read();
  sort(a + 1, a + n + 1);
  for (int i = n; i >= 1; i--)
    s[i] = s[i + 1] - val(i, 0);
  tot = 0;
  pos = 0;
  for (int i = 1; i <= n; i++) {
    tot += mxval(i);
    if (tot >= s[i + 1]) {
      pos = i;
      break;
    }
  }
  if (pos == 0) {
    cout << 0;
    return 0;
  }
  tot -= s[pos + 1];
  int l = 0, r = m;
  while (l <= r) {
    int mid = l + r >> 1;
    if (check(mid, tot))
      ans = mid, r = mid - 1;
    else
      l = mid + 1;
  }
  cout << ans + 1ll * (pos - 1) * m;
  return 0;
  // NOTICE LONG LONG!!!!!
}
// 当权值确定后，显然优先学权值大的
// 一门课学的比对方多就使重要性取max，否则取min
// 既然已经点的比对方多，不如学满
// 该门课学满的收益为(m-x)*r 不学的减益为x*l 总价值为(m-x)*r+x*l
// 按该价值排序依次选完
// 至多只有一门课是不学满(若优则设为r否则设为l)的，其他要么不学(设为l)要么学满（设为r)
// 考虑哪一门不学满 不学满后应二分答案考虑是否可行