#include <iostream>
#include <limits>
#include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

#define EPS (numeric_limits<double>::epsilon())
#define equals(a, b) (fabs((a) - (b)) < EPS)

class Point {
public:
    double x, y;

    Point(double x = 0, double y = 0) : x(x), y(y) {}

    Point operator+(const Point &p) const
    {
        return Point(x + p.x, y + p.y);
    }

    Point operator-(const Point &p) const
    {
        return Point(x - p.x, y - p.y);
    }

    Point operator*(const double &a) const
    {
        return Point(a * x, a * y);
    }

    Point operator/(const double &a) const
    {
        return Point(x / a, y / a);
    }

    double abs()
    {
        return sqrt(norm());
    }

    double norm()
    {
        return x * x + y * y;
    }

    bool operator<(const Point &p) const
    {
        return x != p.x ? x < p.x : y < p.y;
    }

    bool operator==(const Point &p) const
    {
        return equals(x, p.x) && equals(y, p.y);
    }
};

typedef Point Vector;

struct Segment {
    Point p1, p2;
};
typedef Segment Line;


static const int BOTTOM = 0;
static const int LEFT = 1;
static const int RIGHT = 2;
static const int TOP = 3;

class EndPoint {
public:
    Point p;
    int seg_id;
    int type;

    EndPoint() {}

    EndPoint(Point p, int seg_id, int type) : p(p), seg_id(seg_id), type(type) {}

    bool operator<(const EndPoint &ep) const
    {
        return p.y == ep.p.y ? type < ep.type : p.y < ep.p.y;
    }
};

int manhattanIntersection(vector<Segment> S)
{
    int n = S.size();
    vector<EndPoint> EP;

    for (int i = 0; i < n; i++)
    {
        if (S[i].p1.y == S[i].p2.y)
        {
            if (S[i].p1.x > S[i].p2.x)
                swap(S[i].p1, S[i].p2);
        } else
        {
            if (S[i].p1.y > S[i].p2.y)
                swap(S[i].p1, S[i].p2);
        }

        if(S[i].p1.y == S[i].p2.y)
        {
            EP.emplace_back(S[i].p1, i, LEFT);
            EP.emplace_back(S[i].p2, i, RIGHT);
        } else
        {
            EP.emplace_back(S[i].p1, i, BOTTOM);
            EP.emplace_back(S[i].p2, i, TOP);
        }
    }

    sort(EP.begin(), EP.end());

    set<int> BinaryTree;
    int count = 0;

    for(EndPoint endPoint : EP)
    {
        if(endPoint.type == TOP)
            BinaryTree.erase(endPoint.p.x);
        else if(endPoint.type == BOTTOM)
            BinaryTree.insert(endPoint.p.x);
        else if(endPoint.type == LEFT)
        {
            auto begin = BinaryTree.lower_bound(S[endPoint.seg_id].p1.x);
            auto end = BinaryTree.upper_bound(S[endPoint.seg_id].p2.x);
            count += distance(begin, end);
        }
    }
    return count;
}

int main()
{
    int n;
    cin >> n;
    vector<Segment> S;
    S.reserve(n);
    int x1, y1, x2, y2;
    for(int i = 0; i < n; i++)
    {
        cin >> x1 >> y1 >> x2 >> y2;
        S.push_back(Segment{Point(x1, y1), Point(x2, y2)});
    }

    cout << manhattanIntersection(S) << endl;
}
