// Slower C++ solution:
#include<cstdio>

#include<cmath>

#include<cstring>

#include<iostream>

#include<algorithm>

#include<vector>

using namespace std;

#define clr(a,b) memset(a,b,sizeof(a))

#define pb(a)    push_back(a)

#define il       inline

#define reg      register

typedef long long ll;

typedef double db;

const int maxn=10000;

const int minn=200000+5;

struct Point

{

    db x,y;

    Point(){}

    Point(db x,db y):x(x),y(y){}

};

struct Seg

{

    Point a,b;

    int c;

    Seg(Point a,Point b,int c):a(a),b(b),c(c){}

    friend bool operator<(Seg p,Seg q){

        if(p.a.y!=q.a.y) return p.a.y<q.a.y;

    	return p.c!=q.c?p.c<q.c:p.a.x<q.a.x;

    }

};

db  x[minn<<2];

int q,lenx,ans,tree[minn<<2];

vector<Seg> ve;

void init()

{

    clr(tree,0);

    ve.clear();

    lenx=0;

    ans=0;

    return ;

}

void  pushpu(int k,int c)

{

    while(k)

    {

        tree[k]+=c;

        k>>=1;

    }

}

void update(int l,int r,int nu,int c,int k)

{

    if(nu==l&&r==nu)

    {

        pushpu(k,c);

        return ;

    }

    int mind=(l+r)/2;

    if(nu<=mind){update(l,mind,nu,c,k<<1);}

    if(nu>mind) {update(mind+1,r,nu,c,k<<1|1);}

    return ;

}

void query(int l,int r,int L,int R,int k)

{

    if(L<=l&&r<=R)

    {

        ans+=tree[k];

        return ;

    }

    int mind=(l+r)/2;

    if(L<=mind){query(l,mind,L,R,k<<1);}

    if(R>mind) {query(mind+1,r,L,R,k<<1|1);}

    return ;

}

int slove()

{

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

    sort(x,x+lenx);

    int res=0;

    for(reg int i=0;i<ve.size();i++)

    {

        if(ve[i].a.x==ve[i].b.x){

            int nu=lower_bound(x,x+lenx,ve[i].a.x)-x+1;

            int c=ve[i].c>2?-1:ve[i].c;

            update(1,lenx,nu,c,1);

        }

        else

        {

            ans=0;

            int l=lower_bound(x,x+lenx,ve[i].a.x)-x+1;

            int r=lower_bound(x,x+lenx,ve[i].b.x)-x+1;

            query(1,lenx,l,r,1);

            res+=ans;

        }

    }

return res;

}

int main()

{

//    freopen("data.txt","r",stdin);

    init();

    scanf("%d",&q);

    Point a,b;

    while(q--)

    {

        scanf("%lf%lf",&a.x,&a.y);

        scanf("%lf%lf",&b.x,&b.y);

        if(a.x>b.x||a.y>b.y){swap(a,b);}

        if(a.x!=b.x)

        {

            x[lenx++]=a.x;x[lenx++]=b.x;

            ve.pb(Seg(a,b,2));

        }

        else

        {

            x[lenx++]=a.x;

            ve.pb(Seg(a,a,1));

            ve.pb(Seg(b,b,3));

        }

    }

    printf("%d\n",slove());

    return 0;

}




// Faster C++ solution for the same problem (measured speedup: 4.1953496843031015x):
#include<bits/stdc++.h>



using namespace std;



typedef long long ll;



const int maxn=1e5+10;



struct point{

    int x,y;

    point(){}

    point(int x,int y):x(x),y(y){}

} ;



struct segment{

    point a,b;

    int c;                  //用于排序，bottom>(left||right)>top

    segment(point a,point b,int c):a(a),b(b),c(c){}

    bool operator <(const segment & p){

        if(a.y!=p.a.y) return a.y<p.a.y;

        return c!=p.c?c<p.c:a.x<p.a.x;

    }

};



vector<segment> v;



int x[maxn*2];



int tree[maxn<<2];



void up(int p){

    tree[p]=tree[p<<1]+tree[p<<1|1];

}



void modify(int p,int l,int r,int x,int v){

    if(l==r){

        tree[p]+=v;

        return ;

    }

    int mid=l+r>>1;

    if(x<=mid){

        modify(p<<1,l,mid,x,v);

    }else{

        modify(p<<1|1,mid+1,r,x,v);

    }

    up(p);

}



int query(int p,int l,int r,int x,int y){

    if(x<=l&&r<=y){

        return tree[p];

    }

    int mid=l+r>>1;

    int res=0;

    if(x<=mid){

        res+=query(p<<1,l,mid,x,y);

    }

    if(y>mid){

        res+=query(p<<1|1,mid+1,r,x,y);

    }

    return res;

}



int main(){

    int n;

    scanf("%d",&n);

    int len=1;

    for(int i=0;i<n;i++){

        point a,b;

        scanf("%d%d%d%d",&a.x,&a.y,&b.x,&b.y);

        if(a.x!=b.x){

            if(a.x>b.x) swap(a,b);

            x[len++]=a.x;

            x[len++]=b.x;

            v.push_back(segment(a,b,2));

        }else{

            if(a.y>b.y) swap(a,b);

            x[len++]=a.x;

            v.push_back(segment(a,a,1));

            v.push_back(segment(b,b,3));

        }

    }

    len--;

//    printf("%d\n",len);

    sort(x+1,x+len+1);

    len=unique(x+1,x+len+1)-(x+1);

//    for(int i=1;i<=len;i++){

//        printf("%d ",x[i]);

//    }

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

    int vsize=v.size();

//    for(int i=0;i<vsize;i++){

//        printf("%d %d %d\n",v[i].a.x,v[i].a.y,v[i].c);

//    }

    int ans=0;

    for(int i=0;i<vsize;i++){

        if(v[i].a.x==v[i].b.x){

            int id=lower_bound(x+1,x+len+1,v[i].a.x)-x;

//            printf("--%d %d\n",v[i].a.x,id);

            int c=v[i].c==3?-1:1;

            modify(1,1,len,id,c);

//            printf("123123123\n");

        }else{

            int id1=lower_bound(x+1,x+len+1,v[i].a.x)-x;

            int id2=lower_bound(x+1,x+len+1,v[i].b.x)-x;

//            printf("%d %d\n",v[i].a.x,id1);

//            printf("%d %d\n",v[i].b.x,id2);

            ans+=query(1,1,len,id1,id2);

        }

    }

    printf("%d\n",ans);

    return 0;

}