Problem p03585 (C++)

Buggy submission (status: Time Limit Exceeded):
/* Tenka1 Programmer Contest E
   首先,考虑到曼哈顿距离=|xi-xj|+|yi-yj|,
   由这样的性质,可以得到x,y是相互独立的.
   问题被转化为一维的情况,
   现在就是对k*(k-1)/2个点,需要去寻找一个值k使得sigma(abs(k-xi))最小,
   由中位数的性质,显然,k就是这k*(k-1)/2个点的中位数.
   考虑二分答案,现在就是要求对于每个k统计出x坐标小于k的点的数量.
   将所有线按照斜率排序,当x很小时,用一条竖直线段去切这n条线,斜率小的位置最靠下,而斜率大的位置最靠上,
   当x=k时,如果在x<k时l1和l2发生了相交,则l1和l2的相对顺序就会发生变化,
   于是问题就转化为了求逆序对的数量,这是O(nlogn)复杂度的,
   于是就可以得到一个O(nlognlog(eps^(-1)))的解法.
*/
#include <bits/stdc++.h>
#define lim 200000005
using namespace std;
struct line {
  double a, b, c, k;
  int id;
} p[40005];
inline bool cmp(line p, line q) { return p.k < q.k; }
int n, all, nd, t[40005];
int e[40005];
inline void add(int pos) {
  while (pos <= n) {
    e[pos]++;
    pos += (pos & (-pos));
  }
}
inline int ask(int pos) {
  int s = 0;
  while (pos) {
    s += e[pos];
    pos -= (pos & (-pos));
  }
  return s;
}
inline int calc(double mid) {
  int i;
  for (i = 1; i <= n; i++) {
    p[i].k = (-p[i].a / p[i].b) * mid + p[i].c / p[i].b;
  }
  sort(p + 1, p + n + 1, cmp);
  for (i = 1; i <= n; i++) {
    t[i] = p[i].id;
  }
  int ans = 0;
  memset(e, 0, sizeof(e));
  for (i = 1; i <= n; i++) {
    ans += ask(n) - ask(t[i] - 1);
    add(t[i]);
  }
  return ans;
}
inline void solve() {
  int i, tms = 66;
  for (i = 1; i <= n; i++) {
    p[i].id = n - i + 1;
  }
  double l = -lim, r = lim;
  while (tms--) {
    double mid = (l + r) / 2.0;
    if (calc(mid) < nd) {
      l = mid;
    } else {
      r = mid;
    }
  }
  printf("%.12lf", l);
  return;
}
int main() {
  int i;
  scanf("%d", &n);
  all = n * (n - 1) / 2;
  if (all & 1) {
    nd = (all + 1) / 2;
  } else {
    nd = all / 2;
  }
  for (i = 1; i <= n; i++) {
    scanf("%lf%lf%lf", &p[i].a, &p[i].b, &p[i].c);
    p[i].k = -p[i].a / p[i].b;
    // a*x+b*y=c---->y=-a/b*x+c/b
  }
  for (i = 1; i <= n; i++)

    sort(p + 1, p + n + 1, cmp);
  solve();
  printf(" ");
  for (i = 1; i <= n; i++) {
    double tp = p[i].a;
    p[i].a = p[i].b;
    p[i].b = tp;
    p[i].k = -p[i].a / p[i].b;
  }
  sort(p + 1, p + n + 1, cmp);
  solve();
  printf("\n");
  return 0;
}


Fixed submission:
/* Tenka1 Programmer Contest E
   首先,考虑到曼哈顿距离=|xi-xj|+|yi-yj|,
   由这样的性质,可以得到x,y是相互独立的.
   问题被转化为一维的情况,
   现在就是对k*(k-1)/2个点,需要去寻找一个值k使得sigma(abs(k-xi))最小,
   由中位数的性质,显然,k就是这k*(k-1)/2个点的中位数.
   考虑二分答案,现在就是要求对于每个k统计出x坐标小于k的点的数量.
   将所有线按照斜率排序,当x很小时,用一条竖直线段去切这n条线,斜率小的位置最靠下,而斜率大的位置最靠上,
   当x=k时,如果在x<k时l1和l2发生了相交,则l1和l2的相对顺序就会发生变化,
   于是问题就转化为了求逆序对的数量,这是O(nlogn)复杂度的,
   于是就可以得到一个O(nlognlog(eps^(-1)))的解法.
*/
#include <bits/stdc++.h>
#define lim 200000005
using namespace std;
struct line {
  double a, b, c, k;
  int id;
} p[40005];
inline bool cmp(line p, line q) { return p.k < q.k; }
int n, all, nd, t[40005];
int e[40005];
inline void add(int pos) {
  while (pos <= n) {
    e[pos]++;
    pos += (pos & (-pos));
  }
}
inline int ask(int pos) {
  int s = 0;
  while (pos) {
    s += e[pos];
    pos -= (pos & (-pos));
  }
  return s;
}
inline int calc(double mid) {
  int i;
  for (i = 1; i <= n; i++) {
    p[i].k = (-p[i].a / p[i].b) * mid + p[i].c / p[i].b;
  }
  sort(p + 1, p + n + 1, cmp);
  for (i = 1; i <= n; i++) {
    t[i] = p[i].id;
  }
  int ans = 0;
  memset(e, 0, sizeof(e));
  for (i = 1; i <= n; i++) {
    ans += ask(n) - ask(t[i] - 1);
    add(t[i]);
  }
  return ans;
}
inline void solve() {
  int i, tms = 66;
  for (i = 1; i <= n; i++) {
    p[i].id = n - i + 1;
  }
  double l = -lim, r = lim;
  while (tms--) {
    double mid = (l + r) / 2.0;
    if (calc(mid) < nd) {
      l = mid;
    } else {
      r = mid;
    }
  }
  printf("%.12lf", l);
  return;
}
int main() {
  int i;
  scanf("%d", &n);
  all = n * (n - 1) / 2;
  if (all & 1) {
    nd = (all + 1) / 2;
  } else {
    nd = all / 2;
  }
  for (i = 1; i <= n; i++) {
    scanf("%lf%lf%lf", &p[i].a, &p[i].b, &p[i].c);
    p[i].k = -p[i].a / p[i].b;
    // a*x+b*y=c---->y=-a/b*x+c/b
  }
  sort(p + 1, p + n + 1, cmp);
  solve();
  printf(" ");
  for (i = 1; i <= n; i++) {
    double tp = p[i].a;
    p[i].a = p[i].b;
    p[i].b = tp;
    p[i].k = -p[i].a / p[i].b;
  }
  sort(p + 1, p + n + 1, cmp);
  solve();
  printf("\n");
  return 0;
}