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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#define LL long long
#define N 200100
#define M 1010
#define MOD 1000000007
#define FOR(i, l, r) for (int i = (l); i <= (r); i++)
#define CLR(a, x) memset(a, x, sizeof(a))
#define INF 0x7fffffff
#define ALL(x) x.begin(), x.end()
#define pb push_back
#define X first
#define Y second
using namespace std;
typedef unsigned long long ULL;
struct Point {
  LL x, y;
  Point() {}
  Point(LL _x, LL _y) : x(_x), y(_y) {}
  Point operator-(const Point &rhs) const {
    return Point(x - rhs.x, y - rhs.y);
  }
} p[N];
ULL ls[N], rs[N];
LL low[N], up[N];
int n;
vector<LL> all;
LL Cross(Point a, Point b) { return (LL)a.x * b.y - (LL)b.x * a.y; }
LL q1[N], q2[N];
int cmp(Point a, Point b) {
  if (a.x != b.x)
    return a.x < b.x;
  else
    return a.y < b.y;
}
int check(int x, int y, int z) {
  Point t1 = p[y] - p[x];
  Point t2 = p[z] - p[y];
  if (Cross(t1, t2) <= 0)
    return 1;
  else
    return 0;
}
LL area(int x, int y, int z) {
  Point t1 = p[y] - p[x];
  Point t2 = p[z] - p[y];
  return abs(Cross(t1, t2));
}
ULL work(ULL a, ULL b, ULL c) { return (a + c) * b; }
int solve_left() {
  int r1, r2;
  r1 = 1;
  r2 = 1;
  int cur = 1;
  while (p[cur].x == p[1].x && cur <= n)
    cur++;
  low[0] = p[1].y;
  up[0] = p[cur - 1].y;
  ls[0] = 0;
  q1[1] = 1;
  q2[1] = cur - 1;
  for (int i = cur; i <= n; i++) {
    int j = i;
    int k = lower_bound(all.begin(), all.end(), p[i].x) - all.begin();
    while (j + 1 <= n && p[j + 1].x == p[i].x)
      j++;
    low[k] = p[i].y;
    up[k] = p[j].y;
    ls[k] = ls[k - 1] + work(up[k - 1] - low[k - 1], (ULL)(all[k] - all[k - 1]),
                             up[k] - low[k]);
    while (1 < r1 && check(q1[r1 - 1], q1[r1], i)) {
      // cout << check(q1[r1 - 1],q1[r1],i) << endl;
      ls[k] += (ULL)area(q1[r1 - 1], q1[r1], i);
      r1--;
    }
    q1[++r1] = i;
    while (1 < r2 && !check(q2[r2 - 1], q2[r2], j)) {
      ls[k] += (ULL)area(q2[r2 - 1], q2[r2], j);
      r2--;
    }
    q2[++r2] = j;
    i = j;
  }
  return 0;
}
int solve_right() {
  int r1, r2;
  r1 = 1;
  r2 = 1;
  int cur = n;
  while (p[cur].x == p[n].x && cur >= 1)
    cur--;
  int k = lower_bound(all.begin(), all.end(), p[n].x) - all.begin();
  up[k] = p[n].y;
  low[k] = p[cur + 1].y;
  rs[k] = 0;
  q1[1] = cur + 1;
  q2[1] = n;
  for (int i = cur; i >= 1; i--) {
    int j = i;
    int k = lower_bound(all.begin(), all.end(), p[i].x) - all.begin();
    while (j - 1 >= 1 && p[j - 1].x == p[i].x)
      j--;
    up[k] = p[i].y;
    low[k] = p[j].y;
    rs[k] = rs[k + 1] + work(up[k + 1] - low[k + 1], (ULL)(all[k + 1] - all[k]),
                             up[k] - low[k]);
    while (1 < r1 && !check(q1[r1 - 1], q1[r1], j)) {
      rs[k] += (ULL)area(q1[r1 - 1], q1[r1], j);
      r1--;
    }
    q1[++r1] = j;
    while (1 < r2 && check(q2[r2 - 1], q2[r2], i)) {
      rs[k] += (ULL)area(q2[r2 - 1], q2[r2], i);
      r2--;
    }
    q2[++r2] = i;
    i = j;
  }
  return 0;
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%lld%lld", &p[i].x, &p[i].y);
    all.pb(p[i].x);
  }
  sort(all.begin(), all.end());
  all.erase(unique(all.begin(), all.end()), all.end());
  sort(p + 1, p + n + 1, cmp);
  solve_left();
  solve_right();
  // for (int i = 0; i < all.size(); i ++) printf("i = %d,ls = %I64d,rs =
  // %I64d\\n",i,ls[i],rs[i]);
  ULL ans = -1;
  // cout << INF << endl;
  // cout << ans << endl;
  for (int i = 0; i < all.size() - 1; i++)
    ans = min(ans, ls[i] + rs[i + 1]);
  cout << (ans + 1) / 2 << endl;
  // printf("%llu\\n",(ans + 1) / 2);
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#include <iostream>
#define INF 0x3f3f3f3f
using namespace std;
double eps = 1e-10;
double add(double a, double b) {
  if (abs(a + b) < eps * (abs(a) + abs(b)))
    return 0; /**考??差的加法?算**/
  return a + b;
}
struct P {
  double x, y;
  P() {}
  P(double x, double y) : x(x), y(y) {}
  P operator-(P p) /**重?-号**/
  {
    return P(add(x, -p.x), add(y, -p.y));
  }
  double det(P p) /**定?外?**/
  {
    return add(x * p.y, -y * p.x);
  }
};
bool cmp_x(const P &p, const P &q) {
  if (p.x != q.x)
    return p.x < q.x;
  return p.y < q.y;
}
vector<P> convex_hull(P *ps, int n) /**抄模板**/
{
  sort(ps, ps + n, cmp_x);
  int k = 0;
  vector<P> qs(n * 2);
  for (int i = 0; i < n; i++) {
    while (k > 1 && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) <= 0)
      k--;
    qs[k++] = ps[i];
  }
  for (int i = n - 2, t = k; i >= 0; i--) {
    while (k > t && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) <= 0)
      k--;
    qs[k++] = ps[i];
  }
  qs.resize(k - 1);
  return qs;
}
double area(vector<P> v) {
  //    if(r-l+1<3) return 0;
  //    double ans=0;
  //    for(int i=l+1;i+1<r;i++)
  //    {
  //        ans+=fabs(0.5*( (v[i]-v[l]).det(v[i+1]-v[l]) ));
  //    }
  //    return fabs(ans);
  if (v.size() < 3)
    return 0;
  double ans = 0;
  for (int i = 1; i + 1 < v.size(); i++) {
    ans += 0.5 * (v[0] - v[i]).det(v[0] - v[i + 1]);
  }
  return fabs(ans);
}
int n;
P ps[100005];
double check(double x) {
  //    int i;
  //    for(i=0;i<n;i++)
  //    {
  //        if(ps[i].x<=ps[x].x) continue;
  //        else break;
  //    }
  //    return area(ps,0,i)+area(ps,i,n);
  vector<P> p1;
  int i;
  for (i = 0; i < n; i++) {
    if (ps[i].x <= x)
      continue;
    else
      break;
  }
  if (i != 0 && i != n)
    return area(convex_hull(ps, i)) + area(convex_hull(ps + i, n - i));
  else
    return area(convex_hull(ps, n));
}
map<int, int> ma;

int main() {
  scanf("%d", &n);
  memset(ps, 0, sizeof ps);
  ma.clear();
  int cnt = 0;
  for (int i = 0; i < n; i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    ps[cnt].x = a;
    ps[cnt++].y = b;
  }
  sort(ps, ps + n, cmp_x);
  double ans = INF;
  //    int l=-1e9,r=1e9;
  double l = -1e9, r = 1e9;
  int flag = 0;
  double eps = 1e-9;
  while (r - l > eps) {
    //        if(flag++>1e4) break;
    //        int lmid=l+(r-l)/3,rmid=r-(r-l)/3;
    double lmid = l + (r - l) / 3, rmid = r - (r - l) / 3;
    double ans1 = check(lmid), ans2 = check(rmid);
    if (ans1 < ans2) {
      r = rmid;
      ans = min(ans1, ans);
    } else {
      ans = min(ans1, ans);
      l = lmid;
    }
  }
  printf("%lld\\n", (long long)(ans + 0.5));
  return 0;
}