/*
思路就是枚举矩形下面那条先,把所有和其交叉的竖线更新进线段树,然后扫描先向上更新,遇到竖线上端点就在线段树里删掉,遇到横线就更新答案
*/
#include<bits/stdc++.h>
using namespace std;
#define N 20005
#define ll long long 
struct SegV{int x,y1,y2;}v[N];//垂直线 
struct SegH{int y,x1,x2;}h[N];//水平线 
int cmp(SegH a,SegH b){return a.y<b.y;} 
int n,cntv,cnth;
int y[N],cnty,x[N],cntx; 
vector<SegV>Up[N],Down[N];
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[N<<2];
void update(int pos,int v,int l,int r,int rt){
    if(l==r){sum[rt]+=v;return;}
    int m=l+r>>1;
    if(pos<=m)update(pos,v,lson);
    else update(pos,v,rson);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int query(int L,int R,int l,int r,int rt){
    if(L<=l && R>=r)return sum[rt];
    int m=l+r>>1,res=0;
    if(L<=m)res+=query(L,R,lson);
    if(R>m)res+=query(L,R,rson);
    return res; 
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        int x1,x2,y1,y2;
        cin>>x1>>y1>>x2>>y2;
        x[++cntx]=x1;x[++cntx]=x2;
        y[++cnty]=y1;y[++cnty]=y2;
        if(x1==x2){//垂直线 
            cntv++;
            v[cntv].x=x1;
            v[cntv].y1=min(y1,y2);
            v[cntv].y2=max(y1,y2); 
        }
        else {
            cnth++;
            h[cnth].y=y1;
            h[cnth].x1=min(x1,x2);
            h[cnth].x2=max(x1,x2);
        }
    }
    
    sort(x+1,x+1+cntx);
    cntx=unique(x+1,x+1+cntx)-x-1;
    sort(y+1,y+1+cnty);
    cnty=unique(y+1,y+1+cnty)-y-1;
    
    for(int i=1;i<=cnth;i++){
        h[i].y=lower_bound(y+1,y+1+cnty,h[i].y)-y;
        h[i].x1=lower_bound(x+1,x+1+cntx,h[i].x1)-x;
        h[i].x2=lower_bound(x+1,x+1+cntx,h[i].x2)-x;
    }
    for(int i=1;i<=cntv;i++){
        v[i].x=lower_bound(x+1,x+1+cntx,v[i].x)-x;
        v[i].y1=lower_bound(y+1,y+1+cnty,v[i].y1)-y;
        v[i].y2=lower_bound(y+1,y+1+cnty,v[i].y2)-y;
    }
    
    sort(h+1,h+1+cnth,cmp);//给水平线从低到高排序 
    for(int i=1;i<=cntv;i++){//按端点处理垂直线 
        Up[v[i].y2].push_back(v[i]);
        Down[v[i].y1].push_back(v[i]);            
    }
    
    long long ans=0;
    for(int i=1;i<=cnth;i++){
        memset(sum,0,sizeof sum);
        //把所有和h[i]交叉的竖线更新进线段树
        for(int j=1;j<=cntv;j++)
            if(v[j].y1<=h[i].y && v[j].y2>=h[i].y)
                update(v[j].x,1,1,cntx,1);
        //开始向上枚举所有水平线
        int now=h[i].y;//当前的高度
        for(int j=i+1;j<=cnth;j++)if(h[i].y!=h[j].y){
            while(now+1<=h[j].y){
                ++now;
                for(auto v:Up[now-1]){//把这个高度以下的都删掉 
                    if(v.y1<=h[i].y)
                        update(v.x,-1,1,cntx,1); 
                }
            }
            int L=max(h[i].x1,h[j].x1),R=min(h[i].x2,h[j].x2);
            if(L<=R){
                int res=query(L,R,1,cntx,1);
                ans+=res*(res-1)/2;
            }
        }        
    }
    cout<<ans<<endl;
}