Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Segment Intersections: Manhattan Geometry

For given $n$ segments which are parallel to X-axis or Y-axis, find the number of intersections of them.

Input

In the first line, the number of segments $n$ is given. In the following $n$ lines, the $i$-th segment is given by coordinates of its end points in the following format:

$x_1 \; y_1 \; x_2 \; y_2$

The coordinates are given in integers.

Output

Print the number of intersections in a line.

Constraints

$1 \leq n \leq 100,000$

$ -1,000,000,000 \leq x_1, y_1, x_2, y_2 \leq 1,000,000,000$

Two parallel segments never overlap or touch.

The number of intersections $\leq 1,000,000$

Sample Input 1

6
2 2 2 5
1 3 5 3
4 1 4 4
5 2 7 2
6 1 6 3
6 5 6 7

Sample Output 1

3

Solution in C++ (judge verdict: Time Limit Exceeded)

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <sstream>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <functional>
#include <bitset>
#include <deque>
#include <cmath>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;

#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define dow(i, a, b) for(int i = a; i >= b; --i)
#define mem(a) memset(a, 0, sizeof(a))
#define mst(a, b) memset(a, b, sizeof(a))
#define sfi(a) scanf("%d", &a)
#define sfl(a) scanf("%lld", &a)
#define sfd(a) scanf("%lf", &a)
#define sfs(a) scanf("%s", a)
#define pb(a) push_back(a)
#define sync ios::sync_with_stdio(0); cin.tie(0);

const int MAXN = 1000 + 5;
const double EPS = 1e-6;
const double PI = acos(-1.0);

typedef struct Point Point;
typedef struct Line Line;
typedef struct Polygon Polygon;
typedef struct Polygon_convex Polygon_convex;

int cmp(double x);
double sqr(double x);
double det(Point a, Point b);
double dot(Point a, Point b);
double dist(Point a, Point b);
Point rotate_point(Point p, double A);
bool parallel(Line a, Line b);
bool orthogonal(Line a, Line b);
Point PointProjLine(Point p, Line l, Point &ans);
Point reflect(Line l, Point p);
double dis_point_segment(Point p, Line l);
double dis_segment_segment(Line a, Line b);
Line point_make_line(Point a, Point b);
bool in_segment(Line l, Point p);
int dcmp(double k);
double mysqrt(double n);
Point rotate(Point p, double cost, double sint);
pair<Point, Point> crosspoint(Point ap, double ar, Point bp, double br);
bool PointOnSegment(Point p, Point s, Point t);
bool comp_less(Point a, Point b);
void convex_hull(vector<Point> a);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
struct Point
{
	double x, y;
	Point() {}
	Point(double a, double b): x(a), y(b) {}

	friend Point operator -(Point a, Point b)
	{
		return Point(a.x-b.x,a.y-b.y);
	}
	friend Point operator +(Point a, Point b)
	{
		return Point(a.x+b.x,a.y+b.y);
	}
	friend bool operator ==(Point a, Point b)
	{
		return cmp(a.x-b.x)==0 && cmp(a.y-b.y)==0;
	}
	friend Point operator *(Point a, double b)
	{
		return Point(a.x*b,a.y*b);
	}
	friend Point operator *(double a, Point b)
	{
		return Point(a*b.x,a*b.y);
	}
	friend Point operator /(Point a, double b)
	{
		return Point(a.x/b,a.y/b);
	}
	double norm()
	{
		return sqrt(sqr(x)+sqr(y));
	}
};

struct Line
{
	Point a, b;
	Line() {}
	Line(Point x, Point y): a(x), b(y) {}
};

struct Polygon
{
	int n;
	Point a[MAXN];
	Polygon() {}
	int Point_In(Point t)
	{
		int num = 0;
		a[n] = a[0];
		rep(i, 0, n - 1)
		{
			if(PointOnSegment(t, a[i], a[i + 1]))
				return 2;
			int k = cmp(det(a[i + 1] - a[i], t - a[i]));
			int d1 = cmp(a[i].y - t.y);
			int d2 = cmp(a[i + 1].y - t.y);
			if(k > 0 && d1 <= 0 && d2 > 0)
				num++;
			if(k < 0 && d2 <= 0 && d1 > 0)
				num--;
		}
		return num != 0;
	}
};

struct Polygon_convex
{
	vector<Point> P;
	Polygon_convex(int Size = 0)
	{
		P.resize(Size);
	}
} res(2*100000 + 50);

bool comp_less(Point a, Point b)
{
	return cmp(a.x-b.x)<0 || cmp(a.x-b.x)==0 && cmp(a.y-b.y)<0;
}

void convex_hull(vector<Point> a)
{
	sort(a.begin(), a.end(), comp_less);
	a.erase(unique(a.begin(), a.end()), a.end());
	int m = 0;
	int len = a.size();
	rep(i, 0, len - 1)
	{
		while(m>1&&cmp(det(res.P[m-1]-res.P[m-2],a[i]-res.P[m-2]))<0)
			--m;
		res.P[m++] = a[i];
	}
	int k = m;
	len = a.size();
	dow(i, len - 2, 0)
	{
		while(m>k && cmp(det(res.P[m-1]-res.P[m-2],a[i]-res.P[m-2]))<0)
			--m;
		res.P[m++] = a[i];
	}
	res.P.resize(m);
	if(a.size()>1)
		res.P.resize(m-1);
}

bool PointOnSegment(Point p, Point s, Point t)
{
	return cmp(det(p-s,t-s)) == 0 && cmp(dot(p-s,p-t))<=0;
}

bool parallel(Line a, Line b)
{
	return !cmp(det(a.a-a.b,b.a-b.b));
}
	
bool orthogonal(Line a, Line b)
{
	return !cmp(dot(a.a - a.b, b.a - b.b));
}

Point PointProjLine(Point p, Line l)
{
	Point ans;
	double r = dot((l.b-l.a),(p-l.a))/dot(l.b-l.a,l.b-l.a);
	ans = l.a + r*(l.b-l.a);
	return ans;
}

int cmp(double x)
{
	if(abs(x) < EPS)
		return 0;
	if(x > 0)
		return 1;
	return -1;
}

double dis_point_segment(Point p, Line l)
{
	if(cmp(dot(p-l.a,l.b-l.a))<0)
		return (p-l.a).norm();
	if(cmp(dot(p-l.b,l.a-l.b))<0)
		return (p-l.b).norm();
	return abs(det(l.a-p,l.b-p))/dist(l.a,l.b);
}

bool line_make_point(Line a, Line b, Point &res)
{
	if(parallel(a,b))
		return false;
	double s1 = det(a.a-b.a,b.b-b.a);
	double s2 = det(a.b-b.a,b.b-b.a);
	res = (s1*a.b-s2*a.a)/(s1-s2);
	return true;
}

double dis_segment_segment(Line a, Line b)
{
	Point res;
	if(line_make_point(a, b, res) && in_segment(a, res) && in_segment(b, res))
		return 0.;
	return min(min(dis_point_segment(b.a, a), dis_point_segment(b.b, a)), min(dis_point_segment(a.a, b), dis_point_segment(a.b, b)));
}

double sqr(double x)
{
	return x * x;
}

double det(Point a, Point b)
{
	return a.x*b.y-a.y*b.x;
}

double dot(Point a, Point b)
{
	return a.x*b.x+a.y*b.y;
}
double dist(Point a, Point b)
{
	return (a-b).norm();
}

Point rotate_point(Point p, double A)
{
	double tx = p.x, ty = p.y;
	return Point(tx*cos(A)-ty*sin(A),tx*sin(A)+ty*cos(A));
}

Point reflect(Line l, Point p)
{
	return p + ((PointProjLine(p, l) - p) * 2.0);
}

bool in_segment(Line l, Point p)
{
	bool fa = false, fb = false;
	if((cmp(p.x-l.a.x) != -1 && cmp(p.x-l.b.x) != 1) || (cmp(p.x-l.a.x) != 1 && cmp(p.x-l.b.x) != -1))
		fa = true;
	if((cmp(p.y-l.a.y) != -1 && cmp(p.y-l.b.y) != 1) || (cmp(p.y-l.a.y) != 1 && cmp(p.y-l.b.y) != -1))
		fb = true;
	return fa && fb;
}

int dcmp(double k)
{
	return k < -EPS ? -1 : k > EPS ? 1 : 0;
}

double mysqrt(double n)
{
	return sqrt(max(0.0, n));
}

void circle_cross_line(Point a, Point b, Point o, double r, Point ret[], int &num)
{
	double x0 = o.x, y0 = o.y;
	double x1 = a.x, y1 = a.y;
	double x2 = b.x, y2 = b.y;
	double dx = x2 - x1, dy = y2 - y1;
	double A = dx*dx+dy*dy;
	double B = 2*dx*(x1-x0)+2*dy*(y1-y0);
	double C = sqr(x1-x0)+sqr(y1-y0)-sqr(r);
	double delta = B*B-4*A*C;
	num = 0;
	if(dcmp(delta) >= 0)
	{
		double t1 = (-B - mysqrt(delta)) / (2*A);
		double t2 = (-B + mysqrt(delta)) / (2*A);
		ret[num++] = Point(x1 + t1*dx, y1 + t1*dy);
		ret[num++] = Point(x1 + t2*dx, y1 + t2*dy);
	}
	
}

Point rotate(Point p, double cost, double sint)
{
	double x = p.x, y = p.y;
	return Point(x*cost - y*sint, x*sint + y*cost);
}

pair<Point, Point> crosspoint(Point ap, double ar, Point bp, double br)
{
	double d = (ap - bp).norm();
	double cost = (ar*ar + d*d - br*br) / (2*ar*d);
	double sint = sqrt(1. - cost*cost);
	Point v = (bp - ap) / (bp - ap).norm() * ar;
	return make_pair(ap+rotate(v,cost,-sint),ap+rotate(v,cost,sint));
}

const int L = 2;
const LL MOD = 100000 + 50;
const int MAX = 100000 + 50;

struct Node
{
	Point p;
	Point q;
	int id;
	Node(Point p_ = Point(0.,0.), Point q_ = Point(0., 0.), int id_ = 4):p(p_), q(q_), id(id_){}
	friend bool operator ==(Node a, Node b)
	{
		return cmp(a.p.x-b.p.x)==0 && cmp(a.p.y-b.p.y)==0;
	}
	friend bool operator <(Node a, Node b)
	{
		if(cmp(a.p.y-b.p.y)==0)
			return a.id < b.id;
		return a.p.y < b.p.y;
	}
} node[MAX * 2];

set<double> s;

int main()
{	
#ifdef LOCAL
	//~ freopen("in.txt", "r", stdin);
#endif

	int n;
	sfi(n);
	int cnt = 0;
	rep(i, 0, n - 1)
	{
		Point a, b;
		scanf("%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y);
		if(cmp(a.x-b.x)==0)
		{
			if(a.y < b.y)
			{
				node[cnt++] = Node(a, Point(0., 0.), 1);
				node[cnt++] = Node(b, Point(0., 0.), 3);
			}
			else
			{
				node[cnt++] = Node(a, Point(0., 0.), 3);
				node[cnt++] = Node(b, Point(0., 0.), 1);
			}
		}
		else
		{
			if(a.x < b.x)
				node[cnt++] = Node(a, b, 2);
			else
				node[cnt++] = Node(b, a, 2);
		}
		
	}
	sort(node, node + cnt);
	
	int ans = 0;
	rep(i, 0, cnt - 1)
	{
		if(node[i].id == 3)
		{
			set<double>::iterator it = s.find(node[i].p.x);
			s.erase(*it);
		}
		else if(node[i].id == 1)
		{
			s.insert(node[i].p.x);
		}
		else if(node[i].id == 2)
		{
			set<double>::iterator it = s.lower_bound(node[i].p.x);
			set<double>::iterator iter = s.lower_bound(node[i].q.x);
			if(cmp((*iter)-node[i].q.x)==0)
				iter++;
			for(; it != iter; it++)
				ans++;
		}
	}
	printf("%d\n", ans);
	return 0;
}