#include<bits/stdc++.h>
#define A first
#define B second.first
#define C second.second
#define pii pair<int,pair<int,int> >
using namespace std;
const int N = 5e5+1;
pii a[N];
int n,i,b[N],BIT[N],ans;
int get(int pos){
	int x = 0;
	for(;pos; pos -= pos & -pos)
	   x = max(x,BIT[pos]);
	return x;
}
void upd(int pos,int val){
	for(;pos <= n; pos += pos & - pos)
	BIT[pos] = max (BIT[pos], val);
}
bool cmp(pii a, pii b){
	return a.A != b.A ? a.A > b.A : a.B < b.B;
}
main(){
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> n;
	for ( i = 1; i <= n; i++) cin >> a[i].A;
	for ( i = 1; i <= n; i++) cin >> a[i].B, b[i] = a[i].B;
	for ( i = 1; i <= n; i++) cin >> a[i].C;
	sort(a+1,a+n+1,cmp);
	sort(b+1,b+n+1);
	for ( i = 1; i <= n; i++){
		int x = a[i].B;
		int pos = n + 1 - (lower_bound(b+1,b+n+1,x) - b);
		int y = get(pos-1);
		if ( y > a[i].C) ans ++;
		upd(pos,a[i].C);
	}
	cout << ans;
}


#include<bits/stdc++.h>
#define B first
#define I second.first
#define R second.second
using namespace std;
const int N = 5e5+1,M = 1e6;
map< pair<int,pair<int,int> >,int> BIN;
pair<int,pair<int,int> > a[N];
void add(pair<int,pair<int,int> > pos){
	int x = pos.B,y = pos.I, z = pos.R;
	int y1,z1;
	for (;x <=M; x += x&-x)
	for (y1 = y;y1 <=M; y1+=(y1&-y1))
	for (z1 = z;z1 <=M; z1+=(z1&-z1))
	BIN[{x,{y1,z1}}] ++;
}
int ans = 0,i,n;
int sum(pair<int,pair<int,int> > pos){
	int x = pos.B,y = pos.I, z = pos.R,sum = 0,y1,z1;
	for (;x > 0; x -= (x&-x))
	for (y1 = y;y1 > 0; y1-=(y1&-y1))
	for (z1 = z;z1 > 0; z1-=(z1&-z1))
	sum += BIN[{x,{y1,z1}}];
	return sum;
}
main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n;
	for (i = 1; i <= n; i++)
	{	cin >> a[i].B;a[i].B++;}
	for (i = 1; i <= n; i++)
		{cin >> a[i].I;a[i].I++;	}
	for (i = 1; i <= n; i++){
		cin >> a[i].R;a[i].R++;
		add(a[i]);
	}
	int H = sum({M-1,{M-1,M-1}});
	for (i = 1; i <= n; i++){
		 if((H - sum({a[i].B,{M-1,M-1}}) - sum({M,{M,a[i].R}})
		 - sum({M,{a[i].I,M}}) - sum(a[i]) + sum({a[i].B,{a[i].I,M}}) +
		  sum({a[i].B,{M,a[i].R}}) + sum({M,{a[i].I,a[i].R}})) > 0) ans++;
	}
	cout << ans;
}


#include<bits/stdc++.h>
#define B first
#define I second.first
#define R second.second
using namespace std;
const int N = 5e5+1,M = 5e5+2;
map< pair<int,pair<int,int> >,int> BIN;
pair<int,pair<int,int> > a[N];
void add(pair<int,pair<int,int> > pos){
	int x = pos.B,y = pos.I, z = pos.R;
	int y1,z1;
	for (;x <=M; x += x&-x)
	for (y1 = y;y1 <=M; y1+=(y1&-y1))
	for (z1 = z;z1 <=M; z1+=(z1&-z1))
	BIN[{x,{y1,z1}}] ++;
}
int ans = 0,i,n;
int sum(pair<int,pair<int,int> > pos){
	int x = pos.B,y = pos.I, z = pos.R,sum = 0,y1,z1;
	for (;x > 0; x -= (x&-x))
	for (y1 = y;y1 > 0; y1-=(y1&-y1))
	for (z1 = z;z1 > 0; z1-=(z1&-z1))
	sum += BIN[{x,{y1,z1}}];
	return sum;
}
main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n;
	for (i = 1; i <= n; i++)
	{	cin >> a[i].B;a[i].B++;}
	for (i = 1; i <= n; i++)
		{cin >> a[i].I;a[i].I++;	}
	for (i = 1; i <= n; i++){
		cin >> a[i].R;a[i].R++;
		add(a[i]);
	}
	int H = sum({M,{M,M}});
	for (i = 1; i <= n; i++){
		 if((H - sum({a[i].B,{M,M}}) - sum({M,{M,a[i].R}})
		 - sum({M,{a[i].I,M}}) - sum(a[i]) + sum({a[i].B,{a[i].I,M}}) +
		  sum({a[i].B,{M,a[i].R}}) + sum({M,{a[i].I,a[i].R}})) > 0) ans++;
	}
	cout << ans;
}


#include<bits/stdc++.h>
#define int long long
#define B first
#define I second.first
#define R second.second
using namespace std;
const int N = 5e5+1,M = (100)+1;
map< pair<int,pair<int,int> >,int> BIN;
pair<int,pair<int,int> > a[N];
void add(pair<int,pair<int,int> > pos,int val){
	int x = pos.B,y = pos.I, z = pos.R;
	int y1,z1;
	for (;x < M; x += x&-x)
	for (y1 = y;y1 < M; y1+=(y1&-y1))
	for (z1 = z;z1 < M; z1+=(z1&-z1))
	BIN[make_pair(x,make_pair(y1,z1))] ++;
}
int ans = 0;
int sum(pair<int,pair<int,int> > pos){
	int x = pos.B,y = pos.I, z = pos.R,sum = 0,y1,z1;
	for (;x > 0; x -= (x&-x))
	for (y1 = y;y1 > 0; y1-=(y1&-y1))
	for (z1 = z;z1 > 0; z1-=(z1&-z1))
	sum += BIN[make_pair(x,make_pair(y1,z1))];
	return sum;
}
main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{	cin >> a[i].B;a[i].B++;}
	for (int i = 1; i <= n; i++)
		{cin >> a[i].I;a[i].I++;	}
	for (int i = 1; i <= n; i++){
		cin >> a[i].R;a[i].R++;
		add(a[i],1);
	}
	int H = sum({M-1,{M-1,M-1}});
	for (int i = 1; i <= n; i++){
		 if((H - sum({a[i].B,{M-1,M-1}}) - sum({M-1,{M-1,a[i].R}})
		 - sum({M-1,{a[i].I,M-1}}) - sum(a[i]) + sum({a[i].B,{a[i].I,M-1}}) +
		  sum({a[i].B,{M-1,a[i].R}}) + sum({M-1,{a[i].I,a[i].R}})) > 0) ans++;
	}
	cout << ans;
}


#include<bits/stdc++.h>
#define B first
#define I second.first
#define R second.second
using namespace std;
const int N = 5e5+1,M = 1e9;
map< pair<int,pair<int,int> >,int> BIN;
pair<int,pair<int,int> > a[N];
void add(pair<int,pair<int,int> > pos){
	int x = pos.B,y = pos.I, z = pos.R;
	int y1,z1;
	for (;x <=M; x += x&-x)
	for (y1 = y;y1 <=M; y1+=(y1&-y1))
	for (z1 = z;z1 <=M; z1+=(z1&-z1))
	BIN[{x,{y1,z1}}] ++;
}
int ans = 0,i,n;
int sum(pair<int,pair<int,int> > pos){
	int x = pos.B,y = pos.I, z = pos.R,sum = 0,y1,z1;
	for (;x > 0; x -= (x&-x))
	for (y1 = y;y1 > 0; y1-=(y1&-y1))
	for (z1 = z;z1 > 0; z1-=(z1&-z1))
	sum += BIN[{x,{y1,z1}}];
	return sum;
}
main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n;
	for (i = 1; i <= n; i++)
	{	cin >> a[i].B;a[i].B++;}
	for (i = 1; i <= n; i++)
		{cin >> a[i].I;a[i].I++;	}
	for (i = 1; i <= n; i++){
		cin >> a[i].R;a[i].R++;
		add(a[i]);
	}
	int H = sum({M-1,{M-1,M-1}});
	for (i = 1; i <= n; i++){
		 if((H - sum({a[i].B,{M-1,M-1}}) - sum({M,{M,a[i].R}})
		 - sum({M,{a[i].I,M}}) - sum(a[i]) + sum({a[i].B,{a[i].I,M}}) +
		  sum({a[i].B,{M,a[i].R}}) + sum({M,{a[i].I,a[i].R}})) > 0) ans++;
	}
	cout << ans;
}


#include<bits/stdc++.h>
#define B first
#define I second.first
#define R second.second
using namespace std;
const int N = 5e5+1,M = 1e9+1;
map< pair<int,pair<int,int> >,int> BIN;
pair<int,pair<int,int> > a[N];
void add(pair<int,pair<int,int> > pos){
	int x = pos.B,y = pos.I, z = pos.R;
	int y1,z1;
	for (;x < M; x += x&-x)
	for (y1 = y;y1 < M; y1+=(y1&-y1))
	for (z1 = z;z1 < M; z1+=(z1&-z1))
	BIN[make_pair(x,make_pair(y1,z1))] ++;
}
int ans = 0;
int sum(pair<int,pair<int,int> > pos){
	int x = pos.B,y = pos.I, z = pos.R,sum = 0,y1,z1;
	for (;x > 0; x -= (x&-x))
	for (y1 = y;y1 > 0; y1-=(y1&-y1))
	for (z1 = z;z1 > 0; z1-=(z1&-z1))
	sum += BIN[make_pair(x,make_pair(y1,z1))];
	return sum;
}
main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{	cin >> a[i].B;a[i].B++;}
	for (int i = 1; i <= n; i++)
		{cin >> a[i].I;a[i].I++;	}
	for (int i = 1; i <= n; i++){
		cin >> a[i].R;a[i].R++;
		add(a[i]);
	}
	int H = sum({M-1,{M-1,M-1}});
	for (int i = 1; i <= n; i++){
		 if((H - sum({a[i].B,{M-1,M-1}}) - sum({M-1,{M-1,a[i].R}})
		 - sum({M-1,{a[i].I,M-1}}) - sum(a[i]) + sum({a[i].B,{a[i].I,M-1}}) +
		  sum({a[i].B,{M-1,a[i].R}}) + sum({M-1,{a[i].I,a[i].R}})) > 0) ans++;
	}
	cout << ans;
}


#include<bits/stdc++.h>
#define B first
#define I second.first
#define R second.second
using namespace std;
const int N = 5e5+1,M = 1e9+1;
map< pair<int,pair<int,int> >,int> BIN;
pair<int,pair<int,int> > a[N];
void add(pair<int,pair<int,int> > pos,int val){
	int x = pos.B,y = pos.I, z = pos.R;
	int y1,z1;
	for (;x < M; x += x&-x)
	for (y1 = y;y1 < M; y1+=(y1&-y1))
	for (z1 = z;z1 < M; z1+=(z1&-z1))
	BIN[make_pair(x,make_pair(y1,z1))] ++;
}
int ans = 0;
int sum(pair<int,pair<int,int> > pos){
	int x = pos.B,y = pos.I, z = pos.R,sum = 0,y1,z1;
	for (;x > 0; x -= (x&-x))
	for (y1 = y;y1 > 0; y1-=(y1&-y1))
	for (z1 = z;z1 > 0; z1-=(z1&-z1))
	sum += BIN[make_pair(x,make_pair(y1,z1))];
	return sum;
}
main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{	cin >> a[i].B;a[i].B++;}
	for (int i = 1; i <= n; i++)
		{cin >> a[i].I;a[i].I++;	}
	for (int i = 1; i <= n; i++){
		cin >> a[i].R;a[i].R++;
		add(a[i],1);
	}
	int H = sum({M-1,{M-1,M-1}});
	for (int i = 1; i <= n; i++){
		 if((H - sum({a[i].B,{M-1,M-1}}) - sum({M-1,{M-1,a[i].R}})
		 - sum({M-1,{a[i].I,M-1}}) - sum(a[i]) + sum({a[i].B,{a[i].I,M-1}}) +
		  sum({a[i].B,{M-1,a[i].R}}) + sum({M-1,{a[i].I,a[i].R}})) > 0) ans++;
	}
	cout << ans;
}


#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
//#include <atcoder/all>

#define F first
#define S second
#define int long long
#define ll long long
//#define int  unsigned long long
#define pb push_back
//#define double long double

using namespace std;
using namespace __gnu_pbds;

typedef  tree< int , null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 3000000;
const int K = 25;
const int mod = 1e9 + 7;
pair <int, pair<int, int>> a[N];
map <int, int> m;
multiset <int> b[N];
int c[N], t[N];
void build(int v, int tl, int tr){
    if (tl == tr){
        t[v] = c[tl];
        return;
    }
    int mid = (tl + tr) / 2;
    build(v + v, tl, mid);
    build(v + v + 1, mid + 1, tr);
    t[v] = max(t[v + v], t[v + v + 1]);
}
void update(int v, int tl, int tr, int p, int x){
    if (tl == tr){
        t[v] = x;
        return;
    }
    int mid = (tl + tr) / 2;
    if (mid >= p) update(v + v, tl, mid, p, x);
    else update(v + v + 1, mid + 1, tr, p, x);
    t[v] = max(t[v + v], t[v + v + 1]);
}
int query(int v, int tl, int tr, int l, int r){
    if (l > tr || r < tl) return -1e9;
    if (l <= tl && r >= tr) return t[v];
    int mid = (tl + tr) / 2;
    return max(query(v + v, tl, mid, l, r), query(v + v + 1, mid + 1, tr, l, r));
}
main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    int n;
    cin >> n;
    set <int> s;
    for (int i = 1; i <= n; i++) cin >> a[i].F;
    for (int i = 1; i <= n; i++){
        cin >> a[i].S.F;
        s.insert(a[i].S.F);
    }
    for (int i = 1; i <= n; i++) cin >> a[i].S.S;
    int p = 1;
    for (auto x: s){
        m[x] = p;
        p++;
    }
    for (int i = 1; i <= n; i++){
        a[i].S.F = m[a[i].S.F];
        int x = a[i].S.F;
        b[x].insert(a[i].S.S);
    }
    sort(a + 1, a + n + 1);
    for (int i = 1; i < p; i++){
        c[i] = *b[i].rbegin();
    }
    p--;
    build(1, 1, p);
    int ans = 0;
    int k = 1;
    for (int i = 1; i <= n; i++){
        if (i == k){
            while(k <= n && a[k].F == a[i].F){
                int q = a[k].S.F;
                b[q].erase(b[q].find(a[k].S.S));
                if (b[q].size() == 0) c[q] = -1;
                else c[q] = *b[q].rbegin();
                update(1, 1, p, q, c[q]);
                k++;
            }
        }
        int x = query(1, 1, p, a[i].S.F + 1, p);
        if (x > a[i].S.S){
            ans++;
        }
    }
    cout << ans;
}


#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
//#include <atcoder/all>

#define F first
#define S second
#define int long long
#define ll long long
//#define int  unsigned long long
#define pb push_back
//#define double long double

using namespace std;
using namespace __gnu_pbds;

typedef  tree< int , null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2200000;
const int K = 25;
const int mod = 1e9 + 7;
pair <int, pair<int, int>> a[N];
map <int, int> m;
multiset <int> b[N];
int c[N], t[N];
void build(int v, int tl, int tr){
    if (tl == tr){
        t[v] = c[tl];
        return;
    }
    int mid = (tl + tr) / 2;
    build(v + v, tl, mid);
    build(v + v + 1, mid + 1, tr);
    t[v] = max(t[v + v], t[v + v + 1]);
}
void update(int v, int tl, int tr, int p, int x){
    if (tl == tr){
        t[v] = x;
        return;
    }
    int mid = (tl + tr) / 2;
    if (mid >= p) update(v + v, tl, mid, p, x);
    else update(v + v + 1, mid + 1, tr, p, x);
    t[v] = max(t[v + v], t[v + v + 1]);
}
int query(int v, int tl, int tr, int l, int r){
    if (l > tr || r < tl) return -1e9;
    if (l <= tl && r >= tr) return t[v];
    int mid = (tl + tr) / 2;
    return max(query(v + v, tl, mid, l, r), query(v + v + 1, mid + 1, tr, l, r));
}
main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    int n;
    cin >> n;
    set <int> s;
    for (int i = 1; i <= n; i++) cin >> a[i].F;
    for (int i = 1; i <= n; i++){
        cin >> a[i].S.F;
        s.insert(a[i].S.F);
    }
    for (int i = 1; i <= n; i++) cin >> a[i].S.S;
    int p = 1;
    for (auto x: s){
        m[x] = p;
        p++;
    }
    for (int i = 1; i <= n; i++){
        a[i].S.F = m[a[i].S.F];
        int x = a[i].S.F;
        b[x].insert(a[i].S.S);
    }
    sort(a + 1, a + n + 1);
    for (int i = 1; i < p; i++){
        c[i] = *b[i].rbegin();
    }
    p--;
    build(1, 1, p);
    int ans = 0;
    int k = 1;
    for (int i = 1; i <= n; i++){
        if (i == k){
            while(k <= n && a[k].F == a[i].F){
                int q = a[k].S.F;
                b[q].erase(b[q].find(a[k].S.S));
                if (b[q].size() == 0) c[q] = -1;
                else c[q] = *b[q].rbegin();
                update(1, 1, p, q, c[q]);
                k++;
            }
        }
        int x = query(1, 1, p, a[i].S.F + 1, p);
        if (x > a[i].S.S){
            ans++;
        }
    }
    cout << ans;
}


#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
//#include <atcoder/all>

#define F first
#define S second
//#define int long long
#define ll long long
//#define int  unsigned long long
#define pb push_back
//#define double long double

using namespace std;
using namespace __gnu_pbds;

typedef  tree< int , null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2100000;
const int K = 25;
const int mod = 1e9 + 7;
pair <int, pair<int, int>> a[N];
map <int, int> m;
multiset <int> b[N];
int c[N], t[N];
void build(int v, int tl, int tr){
    if (tl == tr){
        t[v] = c[tl];
        return;
    }
    int mid = (tl + tr) / 2;
    build(v + v, tl, mid);
    build(v + v + 1, mid + 1, tr);
    t[v] = max(t[v + v], t[v + v + 1]);
}
void update(int v, int tl, int tr, int p, int x){
    if (tl == tr){
        t[v] = x;
        return;
    }
    int mid = (tl + tr) / 2;
    if (mid >= p) update(v + v, tl, mid, p, x);
    else update(v + v + 1, mid + 1, tr, p, x);
    t[v] = max(t[v + v], t[v + v + 1]);
}
int query(int v, int tl, int tr, int l, int r){
    if (l > tr || r < tl) return -1e9;
    if (l <= tl && r >= tr) return t[v];
    int mid = (tl + tr) / 2;
    return max(query(v + v, tl, mid, l, r), query(v + v + 1, mid + 1, tr, l, r));
}
main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    int n;
    cin >> n;
    set <int> s;
    for (int i = 1; i <= n; i++) cin >> a[i].F;
    for (int i = 1; i <= n; i++){
        cin >> a[i].S.F;
        s.insert(a[i].S.F);
    }
    for (int i = 1; i <= n; i++) cin >> a[i].S.S;
    int p = 1;
    for (auto x: s){
        m[x] = p;
        p++;
    }
    for (int i = 1; i <= n; i++){
        a[i].S.F = m[a[i].S.F];
        int x = a[i].S.F;
        b[x].insert(a[i].S.S);
    }
    sort(a + 1, a + n + 1);
    for (int i = 1; i < p; i++){
        c[i] = *b[i].rbegin();
    }
    p--;
    build(1, 1, p);
    int ans = 0;
    int k = 1;
    for (int i = 1; i <= n; i++){
        if (i == k){
            while(k <= n && a[k].F == a[i].F){
                int q = a[k].S.F;
                b[q].erase(b[q].find(a[k].S.S));
                if (b[q].size() == 0) c[q] = -1;
                else c[q] = *b[q].rbegin();
                update(1, 1, p, q, c[q]);
                k++;
            }
        }
        int x = query(1, 1, p, a[i].S.F + 1, p);
        if (x > a[i].S.S){
            ans++;
        }
    }
    cout << ans;
}


#include <bits/stdc++.h>

#define DEBUG(x)                          \
	{                                     \
		cerr << #x << " = " << x << '\n'; \
	}
#define SQR(x) ((x) * (x))

using namespace std;
const double eps = 1e-5;
const long long base = 1000000007LL;
const int N = 500005;
// const int M = 100005

int BIT[N], n, b[N];
pair<int, pair<int, int>> a[N];

void update(int x, int val)
{
	for (; x > 0; x -= x & -x)
		BIT[x] = max(BIT[x], val);
}

int get(int x)
{
	int res = 0;
	for (; x <= n; x += x & -x)
		res = max(res, BIT[x]);
	return res;
}

bool cmp(pair<int, pair<int, int> > a, pair<int, pair<int, int> > b)
{
	return a.first == b.first ? a.first < b.first : a.second.first > b.second.first;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> n;
	for (int i = 1; i <= n; ++i)
		cin >> a[i].first;
	for (int i = 1; i <= n; ++i)
	{
		cin >> a[i].second.first;
		b[i] = a[i].second.first;
	}
	for (int i = 1; i <= n; ++i)
		cin >> a[i].second.second;
	sort(b + 1, b + n + 1);
	sort(a + 1, a + n + 1, cmp);
	int res = 0;
	for (int i = n; i > 0; --i)
	{
		int pos = lower_bound(b + 1, b + n + 1, a[i].second.first) - b;
		int tmp = get(pos + 1);
		if (tmp > a[i].second.second)
			++res;
		update(pos, a[i].second.second);
	}
	cout << res;

	return 0;
}


#include <bits/stdc++.h>

#define DEBUG(x)                          \
	{                                     \
		cerr << #x << " = " << x << '\n'; \
	}
#define SQR(x) ((x) * (x))

using namespace std;
const double eps = 1e-5;
const long long base = 1000000007LL;
const int N = 500005;
// const int M = 100005

int BIT[N], n, b[N];
pair<int, pair<int, int>> a[N];

void update(int x, int val)
{
	for (; x > 0; x -= x & -x)
		BIT[x] = max(BIT[x], val);
}

int get(int x)
{
	int res = 0;
	for (; x <= n; x += x & -x)
		res = max(res, BIT[x]);
	return res;
}

bool cmp(pair<int, pair<int, int> > a, pair<int, pair<int, int> > b)
{
	return a.first != b.first ? a.first < b.first : a.second.first > b.second.first;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> n;
	for (int i = 1; i <= n; ++i)
		cin >> a[i].first;
	for (int i = 1; i <= n; ++i)
	{
		cin >> a[i].second.first;
		b[i] = a[i].second.first;
	}
	for (int i = 1; i <= n; ++i)
		cin >> a[i].second.second;
	sort(b + 1, b + n + 1);
	sort(a + 1, a + n + 1, cmp);
	int res = 0;
	for (int i = n; i > 0; --i)
	{
		int pos = lower_bound(b + 1, b + n + 1, a[i].second.first) - b;
		int tmp = get(pos + 1);
		if (tmp > a[i].second.second)
			++res;
		update(pos, a[i].second.second);
	}
	cout << res;

	return 0;
}


#include <bits/stdc++.h>

#define DEBUG(x)                          \
	{                                     \
		cerr << #x << " = " << x << '\n'; \
	}
#define SQR(x) ((x) * (x))

using namespace std;
const double eps = 1e-5;
const long long base = 1000000007LL;
const int N = 500005;
// const int M = 100005

int BIT[N], n, b[N];
pair<int, pair<int, int> > a[N];

void update(int x, int val)
{
	for (; x > 0; x -= x & -x) BIT[x] = max(BIT[x], val);
}

int get(int x)
{
	int res = 0;
	for (; x <= n; x += x & -x) res = max(res, BIT[x]);
	return res;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> n;
	for (int i = 1; i <= n; ++i) cin >> a[i].first;
	for (int i = 1; i <= n; ++i)
	{
		cin >> a[i].second.first;
		b[i] = a[i].second.first;
	}
	for (int i = 1; i <= n; ++i) cin >> a[i].second.second;
	sort(b + 1, b + n + 1);
	sort(a + 1, a + n + 1);
	int res = 0;
	for (int i = n; i > 0; --i)
	{
		int pos = lower_bound(b + 1, b + n + 1, a[i].second.first) - b;
		int tmp = get(pos + 1);
		if (tmp > a[i].second.second) ++res;
		update(pos, a[i].second.second);
	}
	cout << res;

	return 0;
}


#include<iostream>
#include<cstdlib>
#include<stdio.h>
#include<map>
#include<algorithm>
using namespace std;
const int maxn=500005;
const int minn=1000000000;
struct Node
{
    int b,l,r;
    bool operator <(const Node &node) const
    {
        return b!=node.b?b<node.b:l!=node.l?l>node.l:r<node.r;
    }
}q[maxn];
int main()
{
    int n;
    map<int,int>qiqi;
    map<int,int>::iterator it;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<n;i++) scanf("%d",&q[i].b);
        for(int i=0;i<n;i++) scanf("%d",&q[i].l);
        for(int i=0;i<n;i++) scanf("%d",&q[i].r);
        sort(q,q+n);
        int count=0;
        qiqi.clear();
        qiqi[minn]=-minn;qiqi[-minn]=minn;
        for(int i=n-1;i>=0;i--)
        {
            it=qiqi.upper_bound(q[i].l);//从map里找比当前lady的第二个关键字大的，it指向它
            if(it->second>q[i].r) count++;//如果map里it指向的lady的第三个关键字大于当前lady的第三个关键字，那么当前lady
            //肯定会自杀。因为先插入到map里的lady的第一关键字肯定大于当前lady的第一关键字（想想我们是怎么排序和查找的）
            //然后it指向的第二个关键字又大于当前lady(upper_bound)，再加上if里表示map里的lady的第三个关键字也大于当前lady
            //所以当前lady 自杀，好啰嗦~~~~~
            else if(qiqi[q[i].l]<q[i].r)//不然我们就要更新map里的值，把map里与当前lady的第二个关键字相同的lady的第三个关键字
            //进行比较，大于则把当前lady插入到map里，同时把map里的其他lady的第二关键字比当前lady小并且第三关键字也比当前lady
            //小的那些人去掉，因为以后在比较和查找过程中遇到那些人要自杀的人遇到当前这个lady就更要自杀了。
            {
                qiqi[q[i].l]=q[i].r;
                for(it=--qiqi.lower_bound(q[i].l);it->second<q[i].r;)
                {
                    //cout<<it->first<<" "<<it->second<<endl;
                    qiqi.erase(it--);
                }
            }
        }
        cout<<count<<endl;

    }
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset((a),(b),sizeof(a))
#define mp(a,b) make_pair(a,b)
#define pi acos(-1)
#define pii pair<int,int>
#define pb push_back
const int INF = 1000000000;
const double eps = 1e-6;
const int maxn = 5e5 + 10;
int n, ans = 0;
struct node {
    int x, y, z;
}a[maxn];

bool cmp (node a, node b) {
    return a.x!=b.x?a.x>b.x:a.y!=b.y?a.y<b.y:a.z>b.z;
}

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].x);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].y);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].z);

    sort(a, a+n, cmp);
    map<int, int> m;
    map<int, int>::iterator it;
    m[INF] = -INF, m[-INF] = INF;//���߽硣��Խ��
    for (int i = 0; i < n; i++) {
        it = m.upper_bound(a[i].y);
        if (it->second > a[i].z)
            ans++;
        else if (m[a[i].y] < a[i].z) {
            m[a[i].y] = a[i].z;
            for (it = --m.lower_bound(a[i].y); it->second < a[i].z; ) {
                m.erase(it);
                it--;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset((a),(b),sizeof(a))
#define mp(a,b) make_pair(a,b)
#define pi acos(-1)
#define pii pair<int,int>
#define pb push_back
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const int maxn = 5e5 + 10;
int n, ans = 0;
struct node {
    int x, y, z;
}a[maxn];

bool cmp (node a, node b) {
    if (a.x == b.x) {
        if (a.y == b.y)
            return a.z > b.z;
        else
            return a.y < b.y;
    }
    else
        return a.x > b.x;
}

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].x);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].y);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].z);

    sort(a, a+n, cmp);
    map<int, int> m;
    map<int, int>::iterator it;
    m[INF] = -INF, m[-INF] = INF;//���߽硣��Խ��
    for (int i = 0; i < n; i++) {
        it = m.upper_bound(a[i].y);
        if (it->second > a[i].z)
            ans++;
        else if (m[a[i].y] < a[i].z) {
            m[a[i].y] = a[i].z;
            for (it = --m.lower_bound(a[i].y); it->second < a[i].z; ) {
                m.erase(it--);
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset((a),(b),sizeof(a))
#define mp(a,b) make_pair(a,b)
#define pi acos(-1)
#define pii pair<int,int>
#define pb push_back
const int INF = 1000000000;
const double eps = 1e-6;
const int maxn = 5e5 + 10;
int n, ans = 0;
struct node {
    int x, y, z;
}a[maxn];

bool cmp (node a, node b) {
    return a.x!=b.x?a.x>b.x:a.y!=b.y?a.y<b.y:a.z>b.z;
}

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].x);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].y);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].z);

    sort(a, a+n, cmp);
    map<int, int> m;
    map<int, int>::iterator it;
    m[INF] = -INF, m[-INF] = INF;//���߽硣��Խ��
    for (int i = 0; i < n; i++) {
        it = m.upper_bound(a[i].y);
        if (it->second > a[i].z)
            ans++;
        else if (m[a[i].y] < a[i].z) {
            m[a[i].y] = a[i].z;
            for (it = --m.lower_bound(a[i].y); it->second < a[i].z; ) {
                m.erase(it--);
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset((a),(b),sizeof(a))
#define mp(a,b) make_pair(a,b)
#define pi acos(-1)
#define pii pair<int,int>
#define pb push_back
const int INF = 1000000000;
const double eps = 1e-6;
const int maxn = 5e5 + 10;
int n, ans = 0;
struct node {
    int x, y, z;
}a[maxn];

bool cmp (node a, node b) {
    if (a.x == b.x) {
        if (a.y == b.y)
            return a.z > b.z;
        else
            return a.y < b.y;
    }
    else
        return a.x > b.x;
}

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].x);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].y);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].z);

    sort(a, a+n, cmp);
    map<int, int> m;
    map<int, int>::iterator it;
    m[INF] = -INF, m[-INF] = INF;//���߽硣��Խ��
    for (int i = 0; i < n; i++) {
        it = m.upper_bound(a[i].y);
        if (it->second > a[i].z)
            ans++;
        else if (m[a[i].y] < a[i].z) {
            m[a[i].y] = a[i].z;
            for (it = --m.lower_bound(a[i].y); it->second < a[i].z; ) {
                m.erase(it);
                it--;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef tree<pair<int, int>, null_type, less_equal<pair<int, int>>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N = 5e5 + 7;

OST bit[N];

void insert(int x, int y) {
	for(int i = x; i < N; i += i & -i)
		bit[i].insert(make_pair(y, x));
}

int query(int x, int y) { int ans = 0;
	for(int i = x; i > 0; i -= i & -i)
		ans += bit[i].order_of_key(make_pair(y+1, 0));
	return ans;
}

int32_t main() {
	ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n; cin >> n;
	map <int, vector <pair <int, int> > > mp;
	vector <int> v;
	for(int i = 1; i <= n; i++) {
		int x, y, z; cin >> x >> y >> z;
		mp[x].push_back(make_pair(y, z));
		v.push_back(y);
	}

	int ptr = 0;
	map <int, int> xx;
	sort(v.begin(), v.end());
	for(int i = 1; i <= n; i++) if(!xx[v[i - 1]]) xx[v[i - 1]] = ++ptr;

	long long ans = 0;

	for(auto [x, z]: mp) {
		for(auto &[p, q]: z) {
			p = xx[p];
			ans += query(p - 1, q - 1);
		}

		for(auto &[p, q]: z) {
			insert(p, q);
		}
	}

	cout << ans << endl;

}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef tree<pair<int, int>, null_type, less <pair<int, int>>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N = 5e5 + 7;

OST bit[N];

void insert(int x, int y) {
	for(int i = x; i < N; i += i & -i)
		bit[i].insert(make_pair(y, x));
}

int query(int x, int y) { int ans = 0;
	for(int i = x; i > 0; i -= i & -i) {
		ans += bit[i].order_of_key(make_pair(y+1, 0));
		if(ans) return 1;
 	}
	return ans;
}

int X[N], Y[N], Z[N];

int32_t main() {
	ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n; cin >> n;
	map <int, vector <pair <int, int> > > mp;
	vector <int> v;

	for(int i = 1; i <= n; i++) cin >> X[i];
	for(int i = 1; i <= n; i++) cin >> Y[i];
	for(int i = 1; i <= n; i++) cin >> Z[i];

	for(int i = 1; i <= n; i++) {
		X[i] = -X[i];
		Y[i] = -Y[i];
		Z[i] = -Z[i];
		mp[X[i]].push_back(make_pair(Y[i], Z[i]));
		v.push_back(Y[i]);
	}

	int ptr = 0;
	map <int, int> xx;
	sort(v.begin(), v.end());
	for(int i = 1; i <= n; i++) if(!xx[v[i - 1]]) xx[v[i - 1]] = ++ptr;

	int ans = 0;

	for(auto [x, z]: mp) {
		for(auto &[p, q]: z) {
			p = xx[p];
			ans += bool(query(p - 1, q - 1));
		}

		for(auto &[p, q]: z) {
			insert(p, q);
		}
	}

	cout << ans << endl;

}


#include <bits/stdc++.h>
using namespace std;

//#define int long long

struct bit{
	int n, s, i; vector <int> t;
	bit(int n) : n(n), t(vector <int> (n + 1, 0)) { }
	void modify(int r, int v) {
		for(i = r; i <= n; i += i & -i) t[i] = max(v, t[i]);
	}
	int MAX(int r) {
		for(s = 0; r >= 1; r -= r & -r) s = max(t[r], s);
		return s;
	}
};

const int N = 5e5 + 7;

int x[N], y[N], z[N];

map <int, vector <pair <int, int> > > mp;

int32_t main() {
	ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n; cin >> n;
	for(int i = 1; i <= n; i++) cin >> x[i];
	for(int i = 1; i <= n; i++) cin >> y[i];
	for(int i = 1; i <= n; i++) cin >> z[i];

	vector <int> v;
	map <int, int> id; int cnt = 0;
	for(int i = 1; i <= n; i++) v.push_back(y[i]);
	sort(v.begin(), v.end());
	for(int x: v) if(!id[x]) id[x] = ++cnt;
	for(int i = 1; i <= n; i++) {
		y[i] = id[y[i]];
		mp[-x[i]].push_back(make_pair(y[i], z[i]));
	}

	bit T(cnt + 1);
	int ans = 0;
	for(auto [k, v]: mp) {
		for(auto [p, q]: v) {
			ans += T.MAX(cnt - p) > q;
		}
		for(auto [p, q]: v) {
			T.modify(cnt - p + 1, q);
		}
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef tree<pair<int, int>, null_type, less_equal<pair<int, int>>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N = 5e5 + 7;

OST bit[N];

void insert(int x, int y) {
	for(int i = x; i < N; i += i & -i)
		bit[i].insert(make_pair(y, x));
}

int query(int x, int y) { int ans = 0;
	for(int i = x; i > 0; i -= i & -i)
		ans += bit[i].order_of_key(make_pair(y+1, 0));
	return ans;
}

int X[N], Y[N], Z[N];

int32_t main() {
	ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n; cin >> n;
	map <int, vector <pair <int, int> > > mp;
	vector <int> v;

	for(int i = 1; i <= n; i++) cin >> X[i];
	for(int i = 1; i <= n; i++) cin >> Y[i];
	for(int i = 1; i <= n; i++) cin >> Z[i];

	for(int i = 1; i <= n; i++) {
		mp[X[i]].push_back(make_pair(Y[i], Z[i]));
		v.push_back(Y[i]);
	}

	int ptr = 0;
	map <int, int> xx;
	sort(v.begin(), v.end());
	for(int i = 1; i <= n; i++) if(!xx[v[i - 1]]) xx[v[i - 1]] = ++ptr;

	long long ans = 0;

	for(auto [x, z]: mp) {
		for(auto &[p, q]: z) {
			p = xx[p];
			ans += query(p - 1, q - 1);
		}

		for(auto &[p, q]: z) {
			insert(p, q);
		}
	}

	cout << ans << endl;

}


#include <bits/stdc++.h>
using namespace std;

//#define int long long

struct RMQ {
        vector <int> t;
        int n;
        RMQ(int n) : n(n) {
                t.resize(n << 1, 0);
        }
        void modify(int p, int v) {
        		v = max(t[p + n], v);
                for(t[p += n] = v; p > 1; p >>= 1) t[p >> 1] = max(t[p], t[p ^ 1]);
        }
        int query(int l, int r) { int res = 0;
                for(l += n, r += n + 1; l < r; l >>= 1, r >>= 1) {
                        if(l & 1) res = max(res, t[l++]);
                        if(r & 1) res = max(res, t[--r]);
                }
                return res;
        }
};

const int N = 5e5 + 7;

int x[N], y[N], z[N];

map <int, vector <pair <int, int> > > mp;

int32_t main() {
	ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n; cin >> n;
	for(int i = 1; i <= n; i++) cin >> x[i];
	for(int i = 1; i <= n; i++) cin >> y[i];
	for(int i = 1; i <= n; i++) cin >> z[i];

	vector <int> v;
	map <int, int> id; int cnt = 0;
	for(int i = 1; i <= n; i++) v.push_back(y[i]);
	sort(v.begin(), v.end());
	for(int x: v) if(!id[x]) id[x] = ++cnt;
	for(int i = 1; i <= n; i++) {
		y[i] = id[y[i]];
		mp[-x[i]].push_back(make_pair(y[i], z[i]));
	}

	RMQ ST(n + 7);
	int ans = 0;
	for(auto [k, v]: mp) {
		for(auto [p, q]: v) {
			ans += ST.query(p + 1, n + 2) > q;
		}
		for(auto [p, q]: v) {
			ST.modify(p, q);
		}
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;

//#define int long long

struct bit{
	int n, s, i; vector <int> t;
	bit(int n) : n(n), t(vector <int> (n + 1, 0)) { }
	void modify(int r, int v) {
		for(i = r; i <= n; i += i & -i) t[i] = max(v, t[i]);
	}
	int MAX(int r) {
		for(s = 0; r >= 1; r -= r & -r) s = max(t[r], s);
		return s;
	}
};

const int N = 5e5 + 7;

map <int, vector <pair <int, int> > > mp;

void compress(vector <int> &v) {
	int n = v.size(), x = 1;
	vector <pair <int, int> > c(n);
	for(int i = 0; i < n; i++) c[i] = {v[i], i};
	sort(c.begin(), c.end());
	for(int i = 0; i < n; i++) {
		x += (i > 0 && c[i].first > c[i - 1].first);
		v[c[i].second] = x;
	}
}

int32_t main() {
	ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n; cin >> n;
	vector <int> x(n), y(n), z(n);
	for(int &k: x) cin >> k;
	for(int &k: y) cin >> k;
	for(int &k: z) cin >> k;
	compress(y);
	for(int i = 0; i < n; ++i) mp[-x[i]].push_back(make_pair(y[i], z[i]));
	bit T(n);
	int ans = 0;
	for(auto [k, v]: mp) {
		for(auto [p, q]: v) {
			ans += T.MAX(n - p) > q;
		}
		for(auto [p, q]: v) {
			T.modify(n - p + 1, q);
		}
	}
	cout << ans << endl;
}


// suicide ladies

#include <iostream>
#include <map>
#include <algorithm>

using std::map;

using std::cin;
using std::cout;

struct Lady {
	int B;
	int I;
	int R;

	bool operator<(Lady& that){
		if (this->B != that.B)
			return this->B < that.B;
		if (this->I != that.I)
			return this->I < that.I;
		return this->R < that.R;
	}
};

const int max_size = 5 * 10e5 + 1;
Lady ladies[max_size];
int n;

void q_sort(Lady* arr, int left, int right) {
	Lady mid = arr[(left + right) / 2];
	int l = left; int r = right;

	while (l <= r) {
		while (arr[l] < mid) ++l;
		while (mid < arr[r]) --r;

		if (l <= r)
			std::swap(arr[l++], arr[r--]);
	}

	if (l < right)
		q_sort(arr, l, right);
	if (left < r)
		q_sort(arr, left, r);
}

int segment_tree[4 * max_size];
int tree_size;

int closest_upper_power_of_2(int value) {
	--value;

	for (int p(1); p < 32; p <<= 1)
		value |= (value >> p);

	return ++value;
}

void assign(int index, int value) {
	index += tree_size - 1;

	if (value <= segment_tree[index])
		return;
	segment_tree[index] = value;

	while (index) {

		index /= 2;

		segment_tree[index] =
			std::max(segment_tree[index * 2], segment_tree[index * 2 + 1]);
	}
}

int get_max(int left, int right) {
	int answer = 0;

	left += tree_size - 1;
	right += tree_size - 1;

	while (left <= right) {

		if (!(left % 2))
			answer = std::max(answer, segment_tree[left]);
		if (right % 2)
			answer = std::max(answer, segment_tree[right]);
		left = (left + 1)/2;
		right = (right - 1)/2;
	}

	return answer;
}

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);

	cin >> n;

	for (int i(0); i < n; ++i) {
		cin >> ladies[i].B;
	}
	for (int i(0); i < n; ++i) {
		cin >> ladies[i].I;
	}
	for (int i(0); i < n; ++i) {
		cin >> ladies[i].R;
	}

	q_sort(ladies, 0, n - 1);

	map<int , int> compressor;
	for (int i(0); i < n; ++i)
		compressor[ladies[i].I] = 0;

	int cntr(0);
	for (auto it = compressor.begin(); it != compressor.end(); ++it) {
		it->second = cntr++;
	}
	for (int i(0); i < n; ++i) {
		ladies[i].I = compressor[ladies[i].I];
	}

	int real_size = compressor.size();
	tree_size  = closest_upper_power_of_2(real_size);

	int answer(0);

	int l = n - 1;
	int r = n - 1;
	while (l >= 0) {
		while (r >= 0 && ladies[r].B == ladies[l].B) {
			if (get_max(ladies[r].I, tree_size) > ladies[r].R) {
				++answer;
			}
			r--;
		}
		while (l > r) {
			assign(ladies[l].I, ladies[l].R);
			l--;
		}
	}

	cout << answer;

	return 0;
}


// suicide ladies

#include <iostream>
#include <map>
#include <algorithm>

using std::istream;
using std::map;

using std::cin;
using std::cout;

struct Lady {
	int B;
	int I;
	int R;

	bool operator<(Lady& that){
		if (this->B != that.B)
			return this->B < that.B;
		if (this->I != that.I)
			return this->I < that.I;
		return this->R < that.R;
	}
};

istream& operator >> (istream& dst, Lady& src) {
	return dst >> src.B >> src.I >> src.R;
}

const int max_size = 5 * 10e5 + 1;
Lady ladies[max_size];
int n;

void q_sort(Lady* arr, int left, int right) {
	Lady mid = arr[(left + right) / 2];
	int l = left; int r = right;

	while (l <= r) {
		while (arr[l] < mid) ++l;
		while (mid < arr[r]) --r;

		if (l <= r)
			std::swap(arr[l++], arr[r--]);
	}

	if (l < right)
		q_sort(arr, l, right);
	if (left < r)
		q_sort(arr, left, r);
}

int segment_tree[4 * max_size];
int size_;

int closest_upper_power_of_2(int value) {
	--value;

	for (int p(1); p < 32; p <<= 1)
		value |= (value >> p);

	return ++value;
}

void assign(int index, int value) {
	index += size_ - 1;

	if (value <= segment_tree[index])
		return;
	segment_tree[index] = value;

	while (index) {

		index /= 2;

		segment_tree[index] =
			std::max(segment_tree[index * 2], segment_tree[index * 2 + 1]);
	}
}

int get_max(int left, int right) {
	int answer = 0;

	left += size_ - 1;
	right += size_ - 1;

	while (left <= right) {

		if (!(left % 2))
			answer = std::max(answer, segment_tree[left]);
		if (right % 2)
			answer = std::max(answer, segment_tree[right]);
		left = (left + 1)/2;
		right = (right - 1)/2;
	}

	return answer;
}

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);

	cin >> n;

	for (int i(0); i < n; ++i) {
		cin >> ladies[i];
	}

	q_sort(ladies, 0, n - 1);

	map<int , int> compressor;
	for (int i(0); i < n; ++i)
		compressor[ladies[i].I] = 0;

	int cntr = 0;
	for (auto it = compressor.begin(); it != compressor.end(); ++it) {
		it->second = cntr++;
	}
	for (int i(0); i < n; ++i) {
		ladies[i].I = compressor[ladies[i].I];
	}

	int tree_size ( closest_upper_power_of_2(compressor.size()) );

	int answer(0);

	for (int i(n - 1); i >= 0;--i) {
		assign(ladies[i].I, ladies[i].R);

		if (get_max(tree_size - ladies[i].I, tree_size) > ladies[i].R)
			++answer;
	}

	cout << answer;

	return 0;
}


// suicide ladies

#include <iostream>
#include <map>
#include <algorithm>

using std::map;

using std::cin;
using std::cout;

struct Lady {
	int B;
	int I;
	int R;

	bool operator<(Lady& that){
		if (this->B != that.B)
			return this->B < that.B;
		if (this->I != that.I)
			return this->I < that.I;
		return this->R < that.R;
	}
};

const int max_size = 5 * 10e5 + 1;
Lady ladies[max_size];
int n;

void q_sort(Lady* arr, int left, int right) {
	Lady mid = arr[(left + right) / 2];
	int l = left; int r = right;

	while (l <= r) {
		while (arr[l] < mid) ++l;
		while (mid < arr[r]) --r;

		if (l <= r)
			std::swap(arr[l++], arr[r--]);
	}

	if (l < right)
		q_sort(arr, l, right);
	if (left < r)
		q_sort(arr, left, r);
}

int segment_tree[4 * max_size];
int tree_size;

int closest_upper_power_of_2(int value) {
	--value;

	for (int p(1); p < 32; p <<= 1)
		value |= (value >> p);

	return ++value;
}

void assign(int index, int value) {
	index += tree_size - 1;

	if (value <= segment_tree[index])
		return;
	segment_tree[index] = value;

	while (index) {

		index /= 2;

		segment_tree[index] =
			std::max(segment_tree[index * 2], segment_tree[index * 2 + 1]);
	}
}

int get_max(int left, int right) {
	int answer = 0;

	left += tree_size - 1;
	right += tree_size - 1;

	while (left <= right) {

		if (!(left % 2))
			answer = std::max(answer, segment_tree[left]);
		if (right % 2)
			answer = std::max(answer, segment_tree[right]);
		left = (left + 1)/2;
		right = (right - 1)/2;
	}

	return answer;
}

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);

	cin >> n;

	for (int i(0); i < n; ++i) {
		cin >> ladies[i].B;
	}
	for (int i(0); i < n; ++i) {
		cin >> ladies[i].I;
	}
	for (int i(0); i < n; ++i) {
		cin >> ladies[i].R;
	}

	q_sort(ladies, 0, n - 1);

	map<int , int> compressor;
	for (int i(0); i < n; ++i)
		compressor[ladies[i].I] = 0;

	int cntr(1);
	for (auto it = compressor.begin(); it != compressor.end(); ++it) {
		it->second = cntr++;
	}
	for (int i(0); i < n; ++i) {
		ladies[i].I = compressor[ladies[i].I];
	}

	int real_size = compressor.size();
	tree_size  = closest_upper_power_of_2(real_size);

	int answer(0);

	int l = n - 1;
	int r = n - 1;
	while (l >= 0) {
		while (r >= 0 && ladies[r].B == ladies[l].B) {
			if (get_max(ladies[r].I - 1, tree_size) > ladies[r].R) {
				++answer;
			}
			r--;
		}
		while (l > r) {
			assign(ladies[l].I, ladies[l].R);
			l--;
		}
	}

	cout << answer;

	return 0;
}


// suicide ladies

#include <iostream>
#include <map>
#include <algorithm>

using std::map;

using std::cin;
using std::cout;

struct Lady {
	int B;
	int I;
	int R;

	bool operator<(Lady& that){
		if (this->B != that.B)
			return this->B < that.B;
		if (this->I != that.I)
			return this->I < that.I;
		return this->R < that.R;
	}
};

const int max_size = 5 * 10e5 + 1;
Lady ladies[max_size];
int n;

void q_sort(Lady* arr, int left, int right) {
	Lady mid = arr[(left + right) / 2];
	int l = left; int r = right;

	while (l <= r) {
		while (arr[l] < mid) ++l;
		while (mid < arr[r]) --r;

		if (l <= r)
			std::swap(arr[l++], arr[r--]);
	}

	if (l < right)
		q_sort(arr, l, right);
	if (left < r)
		q_sort(arr, left, r);
}

int segment_tree[4 * max_size];
int tree_size;

int closest_upper_power_of_2(int value) {
	--value;

	for (int p(1); p < 32; p <<= 1)
		value |= (value >> p);

	return ++value;
}

void assign(int index, int value) {
	index += tree_size - 1;

	if (value <= segment_tree[index])
		return;
	segment_tree[index] = value;

	while (index) {

		index /= 2;

		segment_tree[index] =
			std::max(segment_tree[index * 2], segment_tree[index * 2 + 1]);
	}
}

int get_max(int left, int right) {
	int answer = 0;

	left += tree_size - 1;
	right += tree_size - 1;

	while (left <= right) {

		if (left % 2)
			answer = std::max(answer, segment_tree[left]);
		if (!(right % 2))
			answer = std::max(answer, segment_tree[right]);
		left = (left + 1)/2;
		right = (right - 1)/2;
	}

	return answer;
}

int main() {
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);

	cin >> n;

	for (int i(0); i < n; ++i) {
		cin >> ladies[i].B;
	}
	for (int i(0); i < n; ++i) {
		cin >> ladies[i].I;
	}
	for (int i(0); i < n; ++i) {
		cin >> ladies[i].R;
	}

	q_sort(ladies, 0, n - 1);

	map<int , int> compressor;
	for (int i(0); i < n; ++i)
		compressor[ladies[i].I] = 0;

	int cntr(1);
	for (auto it = compressor.begin(); it != compressor.end(); ++it) {
		it->second = cntr++;
	}
	for (int i(0); i < n; ++i) {
		ladies[i].I = compressor[ladies[i].I];
	}

	int real_size = compressor.size();
	tree_size  = closest_upper_power_of_2(real_size);

	int answer(0);

	int l = n - 1;
	int r = n - 1;
	while (l >= 0) {
		while (r >= 0 && ladies[r].B == ladies[l].B) {
			if (get_max(ladies[r].I + 1, tree_size) > ladies[r].R)
				++answer;

			r--;
		}
		while (l > r) {
			assign(ladies[l].I, ladies[l].R);
			l--;
		}
	}

	cout << answer;

	return 0;
}


#include <iostream>
#include <limits.h>
#include <vector>
#include <cmath>
#include <algorithm>
#include <stdio.h>
#include <queue>

#define left(i) ((i)* 2 + 1)
#define right(i) ((i)* 2 + 2)
#define parent(i) (((i) - 1) / 2)

using namespace std;

struct MaxTree{
    vector<int> v;
    const int NULL_VALUE = INT_MIN;

    void updateNode(int i) {
        v[i] = max(v[left(i)], v[right(i)]);
    }

    MaxTree(int n) {
        v.resize((1<< (int)(ceil(log2(n))+1))-1, NULL_VALUE);
    }
    int a, b;

    int getMax(int i, int l, int r) {

        if (l >= a && r <= b) {
            return v[i];
        } else if (r < a || l > b) {
            return NULL_VALUE;
        } else {
            int m = (l + r) / 2;
            return max(getMax(left(i), l, m), getMax(right(i), m + 1, r));
        }
    }

    int rangeMax(int qa, int qb) {
        a = qa;
        b = qb;
        return getMax(0, 0, v.size() / 2);
    }

    void update_up(int i) {
        updateNode(i);
        if (i != 0) {
            update_up(parent(i));
        }
    }

    void update(int i, int val) {
        int index = v.size() / 2 + i;
        if (v[index] < val) {
            v[index] = val;
            update_up(parent(index));
        }
    }

    void print() {
        int i = 0;
        int livNum = 1;
        while (i < v.size()) {
            for (int j = 0; j < livNum; j++) {
                cout << v[i] << " ";
                i++;
            }
            livNum *= 2;
            cout << "\n";
        }
    }
};

int main() {
    int n;
    cin >> n;
    int x[n], y[n], z[n];
    vector<pair<int, int>> v1;
    vector<pair<int, int>> v2;
    for (int i = 0; i < n; i++) {
        cin >> x[i];
        v1.push_back(pair<int, int>(x[i], i));
    }
    for (int i = 0; i < n; i++) {
        cin >> y[i];
        v2.push_back(pair<int, int>(y[i], i));
    }
    for (int i = 0; i < n; i++) {
        cin >> z[i];
    }
    sort(v1.begin(), v1.end());
    sort(v2.begin(), v2.end());
    int nextY = 0;
    for (int i = 0; i < n; i++) {
        if (i != 0 && v2[i-1].first != v2[i].first) {
            nextY++;
        }
        y[v2[i].second] = nextY;
    }
    /*
    for(int i = 0; i < n; i++) {
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    for(int j = n-1; j >= 0; j--) {
        int i = v1[j].second;
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    */
    MaxTree tree(n);
    queue<int> q;
    int result = 0;
    for (int j = n-1; j >= 0; j--) {
        int i = v1[j].second;
        if (!q.empty() && x[q.front()] > x[i]) {
            while(!q.empty()) {
                tree.update(y[q.front()], z[q.front()]);
                q.pop();
            }
        }
        //tree.print();
        int maxZ = tree.rangeMax(y[i] + 1, n);
        //printf("maxZ: %d\n", maxZ);
        if (maxZ > z[i]) {
            result++;
        }
        q.push(i);
    }
    //tree.print();
    cout << result;
    return 0;
}


#include <iostream>
#include <limits.h>
#include <vector>
#include <cmath>
#include <algorithm>
#include <stdio.h>

#define left(i) ((i)* 2 + 1)
#define right(i) ((i)* 2 + 2)
#define parent(i) (((i) - 1) / 2)

using namespace std;

struct MaxTree{
    vector<int> v;
    const int NULL_VALUE = INT_MIN;

    void updateNode(int i) {
        v[i] = max(v[left(i)], v[right(i)]);
    }

    MaxTree(int n) {
        v.resize((1<< (int)(ceil(log2(n))+1))-1, NULL_VALUE);
    }
    int a, b;

    int getMax(int i, int l, int r) {

        if (l >= a && r <= b) {
            return v[i];
        } else if (r < a || l > b) {
            return NULL_VALUE;
        } else {
            int m = (l + r) / 2;
            return max(getMax(left(i), l, m), getMax(right(i), m + 1, r));
        }
    }

    int rangeMax(int qa, int qb) {
        a = qa;
        b = qb;
        return getMax(0, 0, v.size() / 2);
    }

    void update_up(int i) {
        updateNode(i);
        if (i != 0) {
            update_up(parent(i));
        }
    }

    void update(int i, int val) {
        int index = v.size() / 2 + i;
        if (v[index] < val) {
            v[index] = val;
            update_up(parent(index));
        }
    }

    void print() {
        int i = 0;
        int livNum = 1;
        while (i < v.size()) {
            for (int j = 0; j < livNum; j++) {
                cout << v[i] << " ";
                i++;
            }
            livNum *= 2;
            cout << "\n";
        }
    }
};

int main() {
    int n;
    cin >> n;
    int x[n], y[n], z[n];
    vector<pair<int, int>> v1;
    vector<pair<int, int>> v2;
    for (int i = 0; i < n; i++) {
        cin >> x[i];
        v1.push_back(pair<int, int>(x[i], i));
    }
    for (int i = 0; i < n; i++) {
        cin >> y[i];
        v2.push_back(pair<int, int>(y[i], i));
    }
    for (int i = 0; i < n; i++) {
        cin >> z[i];
    }
    sort(v1.begin(), v1.end());
    sort(v2.begin(), v2.end());
    int nextY = 0;
    for (int i = 0; i < n; i++) {
        if (i != 0 && v2[i-1].first != v2[i].first) {
            nextY++;
        }
        y[v2[i].second] = nextY;
    }
    /*
    for(int i = 0; i < n; i++) {
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    for(int j = n-1; j >= 0; j--) {
        int i = v1[j].second;
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    */
    MaxTree tree(n);
    int result = 0;
    for (int j = n-1; j >= 0; j--) {
        int i = v1[j].second;

        //tree.print();
        int maxZ = tree.rangeMax(y[i] + 1, n);
        //printf("maxZ: %d\n", maxZ);
        if (maxZ > z[i]) {
            result++;
        }
        tree.update(y[i], z[i]);
    }
    //tree.print();
    cout << result;
    return 0;
}


#include <iostream>
#include <limits.h>
#include <vector>
#include <cmath>
#include <algorithm>
#include <stdio.h>

#define left(i) ((i)* 2 + 1)
#define right(i) ((i)* 2 + 2)
#define parent(i) (((i) - 1) / 2)

using namespace std;

struct MaxTree{
    vector<int> v;
    const int NULL_VALUE = INT_MIN;

    void updateNode(int i) {
        v[i] = max(v[left(i)], v[right(i)]);
    }

    MaxTree(int n) {
        v.resize((1<< (int)(ceil(log2(n))+1))-1, NULL_VALUE);
    }
    int a, b;

    int getMax(int i, int l, int r) {

        if (l >= a && r <= b) {
            return v[i];
        } else if (r < a || l > b) {
            return NULL_VALUE;
        } else {
            int m = (l + r) / 2;
            return max(getMax(left(i), l, m), getMax(right(i), m + 1, r));
        }
    }

    int rangeMax(int qa, int qb) {
        a = qa;
        b = qb;
        return getMax(0, 0, v.size() / 2);
    }

    void update_up(int i) {
        updateNode(i);
        if (i != 0) {
            update_up(parent(i));
        }
    }

    void update(int i, int val) {
        int index = v.size() / 2 + i;
        if (v[index] < val) {
            v[index] = val;
            update_up(parent(index));
        }
    }

    void print() {
        int i = 0;
        int livNum = 1;
        while (i < v.size()) {
            for (int j = 0; j < livNum; j++) {
                cout << v[i] << " ";
                i++;
            }
            livNum *= 2;
            cout << "\n";
        }
    }
};

int main() {
    int n;
    cin >> n;
    int x[n], y[n], z[n];
    vector<pair<int, int>> v1;
    vector<pair<int, int>> v2;
    for (int i = 0; i < n; i++) {
        cin >> x[i] >> y[i] >> z[i];
        v1.push_back(pair<int, int>(x[i], i));
        v2.push_back(pair<int, int>(y[i], i));
    }
    sort(v1.begin(), v1.end());
    sort(v2.begin(), v2.end());
    int nextY = 0;
    for (int i = 0; i < n; i++) {
        if (i != 0 && v2[i-1].first != v2[i].second) {
            nextY++;
        }
        y[v2[i].second] = nextY;
    }
    /*
    for(int i = 0; i < n; i++) {
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    for(int j = n-1; j >= 0; j--) {
        int i = v1[j].second;
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    */
    MaxTree tree(n);
    int result = 0;
    for (int j = n-1; j >= 0; j--) {
        int i = v1[j].second;

        //tree.print();
        int maxZ = tree.rangeMax(y[i] + 1, n);
        //printf("maxZ: %d\n", maxZ);
        if (maxZ > z[i]) {
            result++;
        }
        tree.update(y[i], z[i]);
    }
    //tree.print();
    cout << result;
    return 0;
}


#include <iostream>
#include <limits.h>
#include <vector>
#include <cmath>
#include <algorithm>
#include <stdio.h>
#include <queue>

#define left(i) ((i)* 2 + 1)
#define right(i) ((i)* 2 + 2)
#define parent(i) (((i) - 1) / 2)

using namespace std;

struct MaxTree{
    vector<int> v;
    const int NULL_VALUE = INT_MIN;

    void updateNode(int i) {
        v[i] = max(v[left(i)], v[right(i)]);
    }

    MaxTree(int n) {
        v.resize((1<< (int)(ceil(log2(n))+1))-1, NULL_VALUE);
    }
    int a, b;

    int getMax(int i, int l, int r) {

        if (l >= a && r <= b) {
            return v[i];
        } else if (r < a || l > b) {
            return NULL_VALUE;
        } else {
            int m = (l + r) / 2;
            return max(getMax(left(i), l, m), getMax(right(i), m + 1, r));
        }
    }

    int rangeMax(int qa, int qb) {
        a = qa;
        b = qb;
        return getMax(0, 0, v.size() / 2);
    }

    void update_up(int i) {
        updateNode(i);
        if (i != 0) {
            update_up(parent(i));
        }
    }

    void update(int i, int val) {
        int index = v.size() / 2 + i;
        if (v[index] < val) {
            v[index] = val;
            update_up(parent(index));
        }
    }

    void print() {
        int i = 0;
        int livNum = 1;
        while (i < v.size()) {
            for (int j = 0; j < livNum; j++) {
                cout << v[i] << " ";
                i++;
            }
            livNum *= 2;
            cout << "\n";
        }
    }
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin >> n;
    int x[n], y[n], z[n];
    vector<pair<int, int>> v1;
    vector<pair<int, int>> v2;
    for (int i = 0; i < n; i++) {
        cin >> x[i];
        v1.push_back(pair<int, int>(x[i], i));
    }
    for (int i = 0; i < n; i++) {
        cin >> y[i];
        v2.push_back(pair<int, int>(y[i], i));
    }
    for (int i = 0; i < n; i++) {
        cin >> z[i];
    }
    sort(v1.begin(), v1.end());
    sort(v2.begin(), v2.end());
    int nextY = 0;
    for (int i = 0; i < n; i++) {
        if (i != 0 && v2[i-1].first != v2[i].first) {
            nextY++;
        }
        y[v2[i].second] = nextY;
    }
    /*
    for(int i = 0; i < n; i++) {
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    for(int j = n-1; j >= 0; j--) {
        int i = v1[j].second;
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    */
    MaxTree tree(n);
    queue<int> q;
    int result = 0;
    for (int j = n-1; j >= 0; j--) {
        int i = v1[j].second;
        if (!q.empty() && x[q.front()] > x[i]) {
            while(!q.empty()) {
                tree.update(y[q.front()], z[q.front()]);
                q.pop();
            }
        }
        //tree.print();
        int maxZ = tree.rangeMax(y[i] + 1, n);
        //printf("maxZ: %d\n", maxZ);
        if (maxZ > z[i]) {
            result++;
        } else {
            q.push(i);
        }
    }
    //tree.print();
    cout << result;
    return 0;
}


#include <iostream>
#include <limits.h>
#include <vector>
#include <cmath>
#include <algorithm>
#include <stdio.h>
#include <queue>

#define left(i) ((i)* 2 + 1)
#define right(i) ((i)* 2 + 2)
#define parent(i) (((i) - 1) / 2)

using namespace std;

struct MaxTree{
    vector<int> v;
    const int NULL_VALUE = INT_MIN;

    void updateNode(int i) {
        v[i] = max(v[left(i)], v[right(i)]);
    }

    MaxTree(int n) {
        v.resize((1<< (int)(ceil(log2(n))+1))-1, NULL_VALUE);
    }
    int a, b;

    int getMax(int i, int l, int r) {

        if (l >= a && r <= b) {
            return v[i];
        } else if (r < a || l > b) {
            return NULL_VALUE;
        } else {
            int m = (l + r) / 2;
            return max(getMax(left(i), l, m), getMax(right(i), m + 1, r));
        }
    }

    int rangeMax(int qa, int qb) {
        a = qa;
        b = qb;
        return getMax(0, 0, v.size() / 2);
    }

    void update_up(int i) {
        updateNode(i);
        if (i != 0) {
            update_up(parent(i));
        }
    }

    void update(int i, int val) {
        int index = v.size() / 2 + i;
        if (v[index] < val) {
            v[index] = val;
            update_up(parent(index));
        }
    }

    void print() {
        int i = 0;
        int livNum = 1;
        while (i < v.size()) {
            for (int j = 0; j < livNum; j++) {
                cout << v[i] << " ";
                i++;
            }
            livNum *= 2;
            cout << "\n";
        }
    }
};

int main() {
    int n;
    cin >> n;
    int x[n], y[n], z[n];
    vector<pair<int, int>> v1;
    vector<pair<int, int>> v2;
    for (int i = 0; i < n; i++) {
        cin >> x[i];
        v1.push_back(pair<int, int>(x[i], i));
    }
    for (int i = 0; i < n; i++) {
        cin >> y[i];
        v2.push_back(pair<int, int>(y[i], i));
    }
    for (int i = 0; i < n; i++) {
        cin >> z[i];
    }
    sort(v1.begin(), v1.end());
    sort(v2.begin(), v2.end());
    int nextY = 0;
    for (int i = 0; i < n; i++) {
        if (i != 0 && v2[i-1].first != v2[i].first) {
            nextY++;
        }
        y[v2[i].second] = nextY;
    }
    /*
    for(int i = 0; i < n; i++) {
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    for(int j = n-1; j >= 0; j--) {
        int i = v1[j].second;
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    */
    MaxTree tree(n);
    queue<int> q;
    int result = 0;
    for (int j = n-1; j >= 0; j--) {
        int i = v1[j].second;
        if (!q.empty() && x[q.front()] > x[i]) {
            while(!q.empty()) {
                tree.update(y[q.front()], z[q.front()]);
                q.pop();
            }
        }
        //tree.print();
        int maxZ = tree.rangeMax(y[i] + 1, n);
        //printf("maxZ: %d\n", maxZ);
        if (maxZ > z[i]) {
            result++;
        } else {
            q.push(i);
        }
    }
    //tree.print();
    cout << result;
    return 0;
}


#include <iostream>
#include <limits.h>
#include <vector>
#include <cmath>
#include <algorithm>
#include <stdio.h>

#define left(i) ((i)* 2 + 1)
#define right(i) ((i)* 2 + 2)
#define parent(i) (((i) - 1) / 2)

using namespace std;

struct MaxTree{
    vector<int> v;
    const int NULL_VALUE = INT_MIN;

    void updateNode(int i) {
        v[i] = max(v[left(i)], v[right(i)]);
    }

    MaxTree(int n) {
        v.resize((1<< (int)(ceil(log2(n))+1))-1, NULL_VALUE);
    }
    int a, b;

    int getMax(int i, int l, int r) {

        if (l >= a && r <= b) {
            return v[i];
        } else if (r < a || l > b) {
            return NULL_VALUE;
        } else {
            int m = (l + r) / 2;
            return max(getMax(left(i), l, m), getMax(right(i), m + 1, r));
        }
    }

    int rangeMax(int qa, int qb) {
        a = qa;
        b = qb;
        return getMax(0, 0, v.size() / 2);
    }

    void update_up(int i) {
        updateNode(i);
        if (i != 0) {
            update_up(parent(i));
        }
    }

    void update(int i, int val) {
        int index = v.size() / 2 + i;
        if (v[index] < val) {
            v[index] = val;
            update_up(parent(index));
        }
    }

    void print() {
        int i = 0;
        int livNum = 1;
        while (i < v.size()) {
            for (int j = 0; j < livNum; j++) {
                cout << v[i] << " ";
                i++;
            }
            livNum *= 2;
            cout << "\n";
        }
    }
};

int main() {
    int n;
    cin >> n;
    int x[n], y[n], z[n];
    vector<pair<int, int>> v1;
    vector<pair<int, int>> v2;
    for (int i = 0; i < n; i++) {
        cin >> x[i] >> y[i] >> z[i];
        v1.push_back(pair<int, int>(x[i], i));
        v2.push_back(pair<int, int>(y[i], i));
    }
    sort(v1.begin(), v1.end());
    sort(v2.begin(), v2.end());
    int nextY = 0;
    for (int i = 0; i < n; i++) {
        if (i != 0 && v2[i-1].first != v2[i].second) {
            nextY++;
        }
        y[v2[i].second] = nextY;
    }
    /*
    for(int i = 0; i < n; i++) {
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    for(int j = n-1; j >= 0; j--) {
        int i = v1[j].second;
        printf("%d %d %d\n", x[i], y[i], z[i]);
    }
    printf("\n");
    */
    MaxTree tree(n);
    int result = 0;
    for (int j = n-1; j >= 0; j--) {
        int i = v1[j].second;

        tree.print();
        int maxZ = tree.rangeMax(y[i] + 1, n);
        //printf("maxZ: %d\n", maxZ);
        if (maxZ > z[i]) {
            result++;
        }
        tree.update(y[i], z[i]);
    }
    //tree.print();
    cout << result;
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

const int N = 500010;

struct node {
    int l, r, v;
};

struct Node {
    int x, y, z;
};

node tree[4 * N];
Node nd[N];
int n;
vector<int> alls;

void build(int k, int l, int r)
{
    tree[k].l = l, tree[k].r = r;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(2 * k, l, mid);
    build(2 * k + 1, mid + 1, r);
}

void update(int k, int x, int y)
{
    if (tree[k].l == tree[k].r) {
        tree[k].v = max(tree[k].v, y);
        return;
    }
    int mid = (tree[k].l + tree[k].r) / 2;
    if (x <= mid) update(2 * k, x, y);
    else update(2 * k + 1, x, y);
    tree[k].v = max(tree[2 * k].v, tree[2 * k + 1].v);
}

int ask(int k, int a, int b)
{
    if (tree[k].l >= a && tree[k].r <= b) return tree[k].v;
    int mid = (tree[k].l + tree[k].r) / 2, imax = 0;
    if (a <= mid) imax = max(imax, ask(2 * k, a, b));
    if (b > mid) imax = max(imax, ask(2 * k + 1, a, b));
    return imax;
}

bool cmp(Node a, Node b)
{
    if (a.x != b.x) return a.x > b.x;
    if (a.y != b.y) return a.y < b.y;
    return a.z > b.z;
}

int getid(int x)
{
    return lower_bound(alls.begin(), alls.end(), x) - alls.begin() + 1;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &nd[i].x);
    for (int i = 1; i <= n; i++) scanf("%d", &nd[i].y);
    for (int i = 1; i <= n; i++) scanf("%d", &nd[i].z);
    for (int i = 1; i <= n; i++) alls.push_back(nd[i].y);
    sort(nd + 1, nd + n + 1, cmp);
    sort(alls.begin(), alls.end());
    alls.erase(unique(alls.begin(), alls.end()), alls.end());
    int res = 0, len = (int)alls.size();
    build(1, 1, len);
    for (int i = 1; i <= n; i++) {
        int id = getid(nd[i].y);
        if (id + 1 <= len && ask(1, id + 1, len) > nd[i].z) res++;
        update(1, id, nd[i].z);
    }
    printf("%d\n", res);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

const int N = 500010;

struct node {
    int l, r, v;
};

struct Node {
    int x, y, z;
};

node tree[4 * N];
Node nd[N];
int n;
vector<int> alls;

void build(int k, int l, int r)
{
    tree[k].l = l, tree[k].r = r;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(2 * k, l, mid);
    build(2 * k + 1, mid + 1, r);
}

void update(int k, int x, int y)
{
    if (tree[k].l == tree[k].r) {
        tree[k].v = max(tree[k].v, y);
        return;
    }
    int mid = (tree[k].l + tree[k].r) / 2;
    if (x <= mid) update(2 * k, x, y);
    else update(2 * k + 1, x, y);
    tree[k].v = max(tree[2 * k].v, tree[2 * k + 1].v);
}

int ask(int k, int a, int b)
{
    if (tree[k].l >= a && tree[k].r <= b) return tree[k].v;
    int mid = (tree[k].l + tree[k].r) / 2, imax = 0;
    if (a <= mid) imax = max(imax, ask(2 * k, a, b));
    if (b > mid) imax = max(imax, ask(2 * k + 1, a, b));
    return imax;
}

bool cmp(Node a, Node b)
{
    if (a.x != b.x) return a.x > b.x;
    if (a.y != b.y) return a.y > b.y;
    return a.z > b.z;
}

int getid(int x)
{
    return lower_bound(alls.begin(), alls.end(), x) - alls.begin() + 1;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d", &nd[i].x, &nd[i].y, &nd[i].z);
        alls.push_back(nd[i].y);
    }
    sort(nd + 1, nd + n + 1, cmp);
    sort(alls.begin(), alls.end());
    alls.erase(unique(alls.begin(), alls.end()), alls.end());
    int res = 0, len = (int)alls.size();
    build(1, 1, len);
    for (int i = 1; i <= n; i++) {
        int id = getid(nd[i].y);
        if (id + 1 <= len && ask(1, id + 1, len) > nd[i].z) res++;
        update(1, id, nd[i].z);
    }
    printf("%d\n", res);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

const int N = 500010;

struct node {
    int l, r, v;
};

struct Node {
    int x, y, z;
};

node tree[4 * N];
Node nd[N];
int n;
vector<int> alls;

void build(int k, int l, int r)
{
    tree[k].l = l, tree[k].r = r;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(2 * k, l, mid);
    build(2 * k + 1, mid + 1, r);
}

void update(int k, int x, int y)
{
    if (tree[k].l == tree[k].r) {
        tree[k].v = max(tree[k].v, y);
        return;
    }
    int mid = (tree[k].l + tree[k].r) / 2;
    if (x <= mid) update(2 * k, x, y);
    else update(2 * k + 1, x, y);
    tree[k].v = max(tree[2 * k].v, tree[2 * k + 1].v);
}

int ask(int k, int a, int b)
{
    if (tree[k].l >= a && tree[k].r <= b) return tree[k].v;
    int mid = (tree[k].l + tree[k].r) / 2, imax = 0;
    if (a <= mid) imax = max(imax, ask(2 * k, a, b));
    if (b > mid) imax = max(imax, ask(2 * k + 1, a, b));
    return imax;
}

bool cmp(Node a, Node b)
{
    if (a.x != b.x) return a.x > b.x;
    if (a.y != b.y) return a.y > b.y;
    return a.z > b.z;
}

int getid(int x)
{
    return lower_bound(alls.begin(), alls.end(), x) - alls.begin() + 1;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &nd[i].x);
    for (int i = 1; i <= n; i++) scanf("%d", &nd[i].y);
    for (int i = 1; i <= n; i++) scanf("%d", &nd[i].z);
    for (int i = 1; i <= n; i++) alls.push_back(nd[i].y);
    sort(nd + 1, nd + n + 1, cmp);
    sort(alls.begin(), alls.end());
    alls.erase(unique(alls.begin(), alls.end()), alls.end());
    int res = 0, len = (int)alls.size();
    build(1, 1, len);
    for (int i = 1; i <= n; i++) {
        int id = getid(nd[i].y);
        if (id + 1 <= len && ask(1, id + 1, len) > nd[i].z) res++;
        update(1, id, nd[i].z);
    }
    printf("%d\n", res);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

const int N = 500010;

struct node {
    int l, r, v;
};

struct Node {
    int x, y, z;
};

node tree[4 * N];
Node nd[N];
int n;
vector<int> alls;

void build(int k, int l, int r)
{
    tree[k].l = l, tree[k].r = r;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(2 * k, l, mid);
    build(2 * k + 1, mid + 1, r);
}

void update(int k, int x, int y)
{
    if (tree[k].l == tree[k].r) {
        tree[k].v = max(tree[k].v, y);
        return;
    }
    int mid = (tree[k].l + tree[k].r) / 2;
    if (x <= mid) update(2 * k, x, y);
    else update(2 * k + 1, x, y);
    tree[k].v = max(tree[2 * k].v, tree[2 * k + 1].v);
}

int ask(int k, int a, int b)
{
    if (tree[k].l >= a && tree[k].r <= b) return tree[k].v;
    int mid = (tree[k].l + tree[k].r) / 2, imax = 0;
    if (a <= mid) imax = max(imax, ask(2 * k, a, b));
    if (b > mid) imax = max(imax, ask(2 * k + 1, a, b));
    return imax;
}

bool cmp(Node a, Node b)
{
    if (a.x != b.x) return a.x > b.x;
    if (a.y != b.y) return a.y > b.y;
    return a.z > b.z;
}

int getid(int x)
{
    return lower_bound(alls.begin(), alls.end(), x) - alls.begin() + 1;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &nd[i].x);
    for (int i = 1; i <= n; i++) scanf("%d", &nd[i].y);
    for (int i = 1; i <= n; i++) scanf("%d", &nd[i].z);
    for (int i = 1; i <= n; i++) alls.push_back(nd[i].y);
    sort(nd + 1, nd + n + 1, cmp);
    sort(alls.begin(), alls.end());
    alls.erase(unique(alls.begin(), alls.end()), alls.end());
    int res = 0, len = (int)alls.size();
    build(1, 1, len);
    for (int i = 1; i <= n; i++) {
        int id = getid(nd[i].y);
        if (nd[i].x == nd[i - 1].x) {
            update(1, id, nd[i].z);
            continue;
        }
        if (id + 1 <= len && ask(1, id + 1, len) > nd[i].z) res++;
        update(1, id, nd[i].z);
    }
    printf("%d\n", res);
    return 0;
}


#pragma warning(disable:4996)
#include <bits\stdc++.h>
using namespace std;

//============================================================================================
#define p(a) ((a) * (a))
#define forn(i, n, s) for (int i = s; i < n; ++i)
#define forp(i, n, s) for (int i = s; i > n; --i)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> p2ll;
typedef pair<string, int> psi;
//============================================================================================

const int inf = 1 << 30;
int n, ans;
map<int, int> m;

struct person {
	int b, i, r;

	bool operator< (const person &o) const { // find ladies who are more beautiful and more richness
		if (b != o.b) { // move to the last array, intellect ladies at the head of array
			return b < o.b;
		}

		if (i != o.i) {
			return i > o.i;
		}

		return r < o.r;
	}
} l[(int)5e5 + 10];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	//freopen("input.tyt", "rt", stdin);

	cin >> n;

	forn(i, n, 0) cin >> l[i].b;
	forn(i, n, 0) cin >> l[i].i;
	forn(i, n, 0) cin >> l[i].r;

	sort(l, l + n);
	m[inf] = -inf;
	m[-inf] = inf;

	for (int i = n - 1; i >= 0; --i) {
		map<int, int>::iterator it = m.upper_bound(l[i].i); // tìm một người tiệm cận độ thông minh hơn mà lớn hơn so với ng hiện tại
		// first: intellect, second: richness

		if (it->second > l[i].r) { // nếu ng tìm được giàu có hơn ng hiện tại
			++ans;
		}
		else if (m[l[i].i] < l[i].r) { // nếu độ giàu của người có trí thông minh bằng với ng hiện tại
									// nhỏ hơn độ giàu của ng hiện tại
			m[l[i].i] = l[i].r; // cập nhật lại độ giàu của ng này là độ giàu của ng hiện tại
		}

		for (it = --m.lower_bound(l[i].i); it->second < l[i].r; --it) {
			m.erase(it);
		}
	}

	cout << ans;

	return 0;
}


#pragma warning(disable:4996)
#include <bits\stdc++.h>
using namespace std;

//============================================================================================
#define p(a) ((a) * (a))
#define forn(i, n, s) for (int i = s; i < n; ++i)
#define forp(i, n, s) for (int i = s; i > n; --i)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> p2ll;
typedef pair<string, int> psi;
//============================================================================================

const int inf = 1 << 30;
int n, ans;
map<int, int> m;

struct person {
	int b, i, r;

	bool operator< (const person &o) const { // find ladies who are more beautiful and more richness
		if (b != o.b) { // move to the last array, intellect ladies at the head of array
			return b < o.b;
		}

		if (i != o.i) {
			return i > o.i;
		}

		return r < o.r;
	}
} l[(int)5e5 + 10];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	//freopen("input.tyt", "rt", stdin);

	cin >> n;

	forn(i, n, 0) cin >> l[i].b;
	forn(i, n, 0) cin >> l[i].i;
	forn(i, n, 0) cin >> l[i].r;

	sort(l, l + n);
	m[inf] = -inf;
	m[-inf] = inf;
	map<int, int>::iterator it; // first: intellect, second: richness
	for (int i = n - 1; i >= 0; --i) {
		it = m.upper_bound(l[i].i); // tìm một người tiệm cận độ thông minh hơn mà lớn hơn so với ng hiện tại

		if (it->second > l[i].r) { // nếu ng tìm được giàu có hơn ng hiện tại
			++ans;
		}
		else if (m[l[i].i] < l[i].r) { // nếu độ giàu của người có trí thông minh bằng với ng hiện tại
									// nhỏ hơn độ giàu của ng hiện tại
			m[l[i].i] = l[i].r; // cập nhật lại độ giàu của ng này là độ giàu của ng hiện tại

			for (it = --m.lower_bound(l[i].i); it->second < l[i].r; ) {
				m.erase(it--);
			}
		}
	}

	cout << ans;

	return 0;
}


#pragma warning(disable:4996)
#include <bits\stdc++.h>
using namespace std;

//============================================================================================
#define p(a) ((a) * (a))
#define forn(i, n, s) for (int i = s; i < n; ++i)
#define forp(i, n, s) for (int i = s; i > n; --i)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> p2ll;
typedef pair<string, int> psi;
//============================================================================================

const int inf = 1 << 30;
int n, ans;
map<int, int> m;

struct person {
	int b, i, r;

	bool operator< (const person &o) const { // find ladies who are more beautiful and more richness
		if (b != o.b) { // move to the last array, intellect ladies at the head of array
			return b < o.b;
		}

		if (i != o.i) {
			return i > o.i;
		}

		return r < o.r;
	}
} l[(int)5e5 + 10];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	//freopen("input.tyt", "rt", stdin);

	cin >> n;

	forn(i, n, 0) cin >> l[i].b;
	forn(i, n, 0) cin >> l[i].i;
	forn(i, n, 0) cin >> l[i].r;

	sort(l, l + n);
	m[inf] = -inf;
	m[-inf] = inf;

	for (int i = n - 1; i >= 0; --i) {
		map<int, int>::iterator it = m.upper_bound(l[i].i); // tìm một người tiệm cận độ thông minh hơn mà lớn hơn so với ng hiện tại
		// first: intellect, second: richness

		if (it->second > l[i].r) { // nếu ng tìm được giàu có hơn ng hiện tại
			++ans;
		}
		else if (m[l[i].i] < l[i].r) { // nếu độ giàu của người có trí thông minh bằng với ng hiện tại
									// nhỏ hơn độ giàu của ng hiện tại
			m[l[i].i] = l[i].r; // cập nhật lại độ giàu của ng này là độ giàu của ng hiện tại

			for (it = --m.lower_bound(l[i].i); it->second < l[i].r; --it) {
				m.erase(it);
			}
		}
	}

	cout << ans;

	return 0;
}


#pragma warning(disable:4996)
#include <bits\stdc++.h>
using namespace std;

//============================================================================================
#define p(a) ((a) * (a))
#define forn(i, n, s) for (int i = s; i < n; ++i)
#define forp(i, n, s) for (int i = s; i > n; --i)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> p2ll;
typedef pair<string, int> psi;
//============================================================================================

const int inf = 1 << 30;
int n, ans;
map<int, int> m;

struct person {
	int b, i, r;

	bool operator< (const person &o) const { // find ladies who are more beautiful and more richness
		if (b != o.b) { // move to the last array, intellect ladies at the head of array
			return b < o.b;
		}

		if (i != o.i) {
			return i > o.i;
		}

		return r < o.r;
	}
} l[(int)5e5 + 10];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);

	cin >> n;

	forn(i, n, 0) cin >> l[i].b;
	forn(i, n, 0) cin >> l[i].i;
	forn(i, n, 0) cin >> l[i].r;

	sort(l, l + n);
	m[inf] = -inf; // người thông minh nhất cũng là ng nghèo nhất (trong mảng map, người này đứng cuối cùng)
	m[-inf] = inf; // người ngu nhất cũng là người giàu nhất (trong mảng map, người này đứng đầu tiên)
	map<int, int>::iterator it; // first: intellect, second: richness

	for (int i = n - 1; i >= 0; --i) {
		it = m.upper_bound(l[i].i); // tìm một người khôn hơn người l[i] sao cho 2 giá trị này tiệm cận vs nhau

		if (it->second > l[i].r) { // nếu ng tìm được giàu có hơn ng l[i]
			++ans;
		}
		else if (m[l[i].i] < l[i].r) { // kiểm tra trong map, nếu độ giàu của người có trí khôn bằng l[i].i nhỏ hơn độ giàu của người l[i] hiện tại
			m[l[i].i] = l[i].r; // cập nhật lại độ giàu lớn hơn cho người này (vì mục tiêu ta xóa những người có giá trị cao hơn)

			for (it = --m.lower_bound(l[i].i); it->second < l[i].r; ) { // xóa những người ngu hơn và nghèo hơn người mới thêm vào map
				m.erase(it--); // người mới vô chắc chắn sẽ xấu hơn những người có sẵn trong map, nhưng chắc chắc sẽ đẹp hơn những ng chưa
			} // vào trong map, nên vì vậy ta sẽ xóa như cách lí giải ở trên
		}
	}

	cout << ans;

	return 0;
}


#pragma warning(disable:4996)
#include <bits\stdc++.h>
using namespace std;

//============================================================================================
#define p(a) ((a) * (a))
#define forn(i, n, s) for (int i = s; i < n; ++i)
#define forp(i, n, s) for (int i = s; i > n; --i)
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> p2ll;
typedef pair<string, int> psi;
//============================================================================================

const int inf = 1 << 30;
int n, ans;
map<int, int> m;

struct person {
	int b, i, r;

	bool operator< (const person &o) const { // find ladies who are more beautiful and more richness
		if (b != o.b) { // move to the last array, intellect ladies at the head of array
			return b < o.b;
		}

		if (i != o.i) {
			return i > o.i;
		}

		return r < o.r;
	}
} l[(int)5e5];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	//freopen("input.tyt", "rt", stdin);

	cin >> n;

	forn(i, n, 0) cin >> l[i].b;
	forn(i, n, 0) cin >> l[i].i;
	forn(i, n, 0) cin >> l[i].r;

	sort(l, l + n);
	m[inf] = -inf;
	m[-inf] = inf;
	map<int, int>::iterator it; // first: intellect, second: richness

	for (int i = n - 1; i >= 0; --i) {
		it = m.upper_bound(l[i].i); // tìm một người tiệm cận độ thông minh hơn mà lớn hơn so với ng hiện tại

		if (it->second > l[i].r) { // nếu ng tìm được giàu có hơn ng hiện tại
			++ans;
		}
		else if (m[l[i].i] < l[i].r) { // nếu độ giàu của người có trí thông minh bằng với ng hiện tại
									// nhỏ hơn độ giàu của ng hiện tại
			m[l[i].i] = l[i].r; // cập nhật lại độ giàu của ng này là độ giàu của ng hiện tại

			for (it = --m.lower_bound(l[i].i); it->second < l[i].r; it) {
				m.erase(--it);
			}
		}
	}

	/*cout << endl;
	forn(i, n, 0) cout << l[i].b << " "; cout << endl;
	forn(i, n, 0) cout << l[i].i << " "; cout << endl;
	forn(i, n, 0) cout << l[i].r << " "; cout << endl;*/

	cout << ans;

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

using DB = double;
const DB EPS = 1e-8;
const DB PI = acos(-1);
const DB INF = 1e100;

inline DB sqr(DB x) {
	return x * x;
}

struct PT {
	DB x, y;
	PT (DB x = 0, DB y = 0) : x(x), y(y) {}
	void in() {
		scanf("%lf%lf", &x, &y);
		x /= 1000, y /= 1000;
	}
};

PT operator + (PT a, PT b) {
	return PT(a.x + b.x, a.y + b.y);
}

PT operator - (PT a, PT b) {
	return PT(a.x - b.x, a.y - b.y);
}

PT operator * (PT a, DB b) {
	return PT(a.x * b, a.y * b);
}

PT operator / (PT a, DB b) {
	return PT(a.x / b, a.y / b);
}

DB dis2(PT p) {
	return sqr(p.x) + sqr(p.y);
}

DB dis(PT p) {
	return sqrt(dis2(p));
}

DB scal(PT a, PT b) {
	return a.x * b.x + a.y * b.y;
}

DB getAngle(PT p) {
	return atan2(p.y, p.x);
}

int posCirLine(PT p, DB r, PT p1, PT p2, PT *q) {
	DB a = dis2(p1 - p2);
	DB b = scal(p - p1, p2 - p1);
	DB c = dis2(p - p1) - sqr(r);
	DB d2 = sqr(b) - a * c;
	if (d2 < -EPS) return 0;
	DB d = sqrt(fabs(d2));
	q[0] = p1 + (p2 - p1) * ((b + d) / a);
	q[1] = p1 + (p2 - p1) * ((b - d) / a);
	if (d2 < EPS) return 1;
	return 2;
}

const int N = 55000;
const int M = N + N;
PT A[N], B[N];

struct Line{
	DB a, b;
	void in() {
		scanf("%lf%lf", &a, &b);
		a /= 1000, b /= 1000;
	}
	Line (DB a = 0, DB b = 0) : a(a), b(b) {}
	PT cross(Line l) {
		if (fabs(a - l.a) < EPS) return PT(INF, INF);
		DB x = (l.b - b) / (a - l.a);
		DB y = a * x + b;
		return PT (x, y);
	}
} L[N];

int b[M];

void add(int idx, int v) {
	for (idx++; idx < M; idx += idx & -idx) b[idx] += v;
}

int get(int idx) {
	int ret = 0;
	for (idx++; idx; idx -= idx & -idx) ret += b[idx];
	return ret;
}

struct query{
	DB val;
	int id, sig;
	query(DB val = 0, int id = 0, int sig = 1) : val(val), id(id), sig(sig) {}
	bool operator <(const query &q) const {
		return val < q.val;
	}
};

int n, m;
PT P;
vector<query> VQ;
int to[M], id[M];
int vec[M], tmp[M];

long long can(DB r, bool CALC, DB &sum) {
	VQ.clear();
	for (int i = 0; i < n; i++) {
		PT tem[2];
		if (posCirLine(P, r, A[i], B[i], tem)) {
			DB ang[2];
			for (int j = 0; j < 2; j++) ang[j] = getAngle(tem[j] - P);
			if (ang[1] < ang[0]) swap(ang[0], ang[1]);
			VQ.push_back(query(ang[0], i, 1));
			VQ.push_back(query(ang[1], i, -1));
		}
	}
	for (int i = 0; i < VQ.size(); i++) id[i] = i;
	sort(id, id + VQ.size(), [](int a, int b) { return VQ[a].val < VQ[b].val; });
	sum = 0;
	long long cnt = 0;
	memset(b, 0, sizeof b);
	int vn = 0;
	int now = 0, all = 0;
	for (int i = 0; i < VQ.size(); i++) {
		query t = VQ[id[i]];
		if (t.sig == 1) {
			to[t.id] = now;
			add(now, 1);
			++all;
			if (CALC) vec[vn++] = t.id;
		} else {
			cnt += (all - get(to[t.id]));
			add(to[t.id], -1);
			--all;
			if (CALC) {
				int tn = 0;
				while (vn && vec[vn - 1] != t.id) {
					int a = t.id, b = vec[vn - 1];
					assert(fabs(L[a].a - L[b].a) > EPS);
					sum += dis(P - L[a].cross(L[b]));
					tmp[tn++] = b;
					vn--;
				}
				if (vn) vn--;
				while (tn) {
					vec[vn++] = tmp[tn - 1];
					--tn;
				}
			}
		}
		++now;
	}
	return cnt;
}

int main() {
//	freopen("in.txt", "r", stdin);
	scanf("%d", &n);
	P.in(); scanf("%d", &m);
	for (int i = 0; i < n; i++) {
		L[i].in();
		A[i] = PT(0, L[i].b);
		B[i] = PT(1, L[i].a + L[i].b);
	}
	DB st = 0, en = 1e10;
	DB ans;
	for (int times = 0; times < 60; times++) {
		DB md = (st + en) / 2;
		if (can(md, 0, ans) <= m) st = md;
		else en = md;
	}
	long long cnt = can(st, 1, ans);
	printf("%.10lf\n", ans + st * (m - cnt));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

using DB = double;
const DB EPS = 1e-8;
const DB PI = acos(-1);
const DB INF = 1e100;

inline DB sqr(DB x) {
	return x * x;
}

struct PT {
	DB x, y;
	PT (DB x = 0, DB y = 0) : x(x), y(y) {}
	void in() {
		scanf("%lf%lf", &x, &y);
		x /= 1000, y /= 1000;
	}
};

PT operator + (PT a, PT b) {
	return PT(a.x + b.x, a.y + b.y);
}

PT operator - (PT a, PT b) {
	return PT(a.x - b.x, a.y - b.y);
}

PT operator * (PT a, DB b) {
	return PT(a.x * b, a.y * b);
}

PT operator / (PT a, DB b) {
	return PT(a.x / b, a.y / b);
}

DB dis2(PT p) {
	return sqr(p.x) + sqr(p.y);
}

DB dis(PT p) {
	return sqrt(dis2(p));
}

DB scal(PT a, PT b) {
	return a.x * b.x + a.y * b.y;
}

DB getAngle(PT p) {
	return atan2(p.y, p.x);
}

int posCirLine(PT p, DB r, PT p1, PT p2, PT *q) {
	DB a = dis2(p1 - p2);
	DB b = scal(p - p1, p2 - p1);
	DB c = dis2(p - p1) - sqr(r);
	DB d2 = sqr(b) - a * c;
	if (d2 < EPS) return 0;
	DB d = sqrt(fabs(d2));
	q[0] = p1 + (p2 - p1) * ((b + d) / a);
	q[1] = p1 + (p2 - p1) * ((b - d) / a);
	return 1;
}

const int N = 55000;
const int M = N + N;
PT A[N], B[N];

struct Line{
	DB a, b;
	void in() {
		scanf("%lf%lf", &a, &b);
		a /= 1000, b /= 1000;
	}
	Line (DB a = 0, DB b = 0) : a(a), b(b) {}
	PT cross(Line l) {
		if (fabs(a - l.a) < EPS) return PT(INF, INF);
		DB x = (l.b - b) / (a - l.a);
		DB y = a * x + b;
		return PT (x, y);
	}
} L[N];

int b[M];

void add(int idx, int v) {
	for (idx++; idx < M; idx += idx & -idx) b[idx] += v;
}

int get(int idx) {
	int ret = 0;
	for (idx++; idx; idx -= idx & -idx) ret += b[idx];
	return ret;
}

struct query{
	DB val;
	int id, sig;
	query(DB val = 0, int id = 0, int sig = 1) : val(val), id(id), sig(sig) {}
	bool operator <(const query &q) const {
		return val < q.val;
	}
};

int n, m;
PT P;
query VQ[M];
int to[M], id[M];
int vec[M], tmp[M];

long long can(DB r, bool CALC, DB &sum) {
	int vqn = 0;
	for (int i = 0; i < n; i++) {
		PT tem[2];
		if (posCirLine(P, r, A[i], B[i], tem)) {
			DB ang[2];
			for (int j = 0; j < 2; j++) ang[j] = getAngle(tem[j] - P);
			if (ang[1] < ang[0]) swap(ang[0], ang[1]);
			VQ[vqn++] = query(ang[0], i, 1);
			VQ[vqn++] = query(ang[1], i, -1);
		}
	}
	for (int i = 0; i < vqn; i++) id[i] = i;
	sort(id, id + vqn, [](int a, int b) { return VQ[a].val < VQ[b].val; });
	sum = 0;
	long long cnt = 0;
	memset(b, 0, sizeof b);
	int vn = 0;
	int now = 0, all = 0;
	for (int i = 0; i < vqn; i++) {
		query t = VQ[id[i]];
		if (t.sig == 1) {
			to[t.id] = now;
			add(now, 1);
			++all;
			if (CALC) vec[vn++] = t.id;
		} else {
			cnt += (all - get(to[t.id]));
			add(to[t.id], -1);
			--all;
			if (CALC) {
				int tn = 0;
				while (vn && vec[vn - 1] != t.id) {
					int a = t.id, b = vec[vn - 1];
					assert(fabs(L[a].a - L[b].a) > EPS);
					sum += dis(P - L[a].cross(L[b]));
					tmp[tn++] = b;
					vn--;
				}
				if (vn) vn--;
				while (tn) {
					vec[vn++] = tmp[tn - 1];
					--tn;
				}
			}
		}
		++now;
	}
	return cnt;
}

int main() {
	scanf("%d", &n);
	P.in(); scanf("%d", &m);
	for (int i = 0; i < n; i++) {
		L[i].in();
		A[i] = PT(0, L[i].b);
		B[i] = PT(1, L[i].a + L[i].b);
	}
	DB st = 0, en = 1e10;
	DB ans;
	int now = clock();
	for (int times = 0; times < 60; times++) {
		DB md = (st + en) / 2;
		if (can(md, 0, ans) <= m) st = md;
		else en = md;
	}
	long long cnt = can(st, 1, ans);
	printf("%.10lf\n", ans + st * (m - cnt));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

using DB = double;
const DB EPS = 1e-8;
const DB PI = acos(-1);

inline DB sqr(DB x) {
	return x * x;
}

struct PT {
	DB x, y;
	PT (DB x = 0, DB y = 0) : x(x), y(y) {}
	void in() {
		scanf("%lf%lf", &x, &y);
		x /= 1000, y /= 1000;
	}
};

PT operator + (PT a, PT b) {
	return PT(a.x + b.x, a.y + b.y);
}

PT operator - (PT a, PT b) {
	return PT(a.x - b.x, a.y - b.y);
}

PT operator * (PT a, DB b) {
	return PT(a.x * b, a.y * b);
}

PT operator / (PT a, DB b) {
	return PT(a.x / b, a.y / b);
}

DB dis2(PT p) {
	return sqr(p.x) + sqr(p.y);
}

DB dis(PT p) {
	return sqrt(dis2(p));
}

DB scal(PT a, PT b) {
	return a.x * b.x + a.y * b.y;
}

DB scal(PT a, PT b, PT c) {
	return scal(b - a, c - a);
}

DB getAngle(PT p) {
	return atan2(p.y, p.x);
}

int posCirLine(PT p, DB r, PT p1, PT p2, PT *q) {
	DB a, b, c, d2, d;
	a = dis2(p1 - p2);
	b = scal(p1, p, p2);
	c = dis2(p - p1) - sqr(r);
	d2 = sqr(b) - a * c;
	if (d2 < -EPS) return 0;
	d = sqrt(fabs(d2));
	q[0] = p1 + (p2 - p1) * ((b + d) / a);
	q[1] = p1 + (p2 - p1) * ((b - d) / a);
	if (d2 < EPS) return 1;
	return 2;
}

const int N = 55000;
const int M = N + N;
PT A[N], B[N];

struct Line{
	DB a, b;
	void in() {
		scanf("%lf%lf", &a, &b);
		a /= 1000, b /= 1000;
	}
	Line (DB a = 0, DB b = 0) : a(a), b(b) {}
	PT cross(Line l) {
		DB x = (l.b - b) / (a - l.a);
		DB y = a * x + b;
		return PT (x, y);
	}
} L[N];

struct bit{
	int b[M];
	void clear() {
		memset(b, 0, sizeof b);
	}
	void add(int idx, int v) {
		for (idx++; idx < M; idx += idx & -idx) b[idx] += v;
	}
	int get(int idx) {
		int ret = 0;
		for (idx++; idx; idx -= idx & -idx) ret += b[idx];
		return ret;
	}
} BIT;

struct query{
	DB val;
	int id, sig;
	query(DB val = 0, int id = 0, int sig = 1) : val(val), id(id), sig(sig) {}
	bool operator <(const query &q) const {
		return val < q.val;
	}
};

int n, m;
PT P;
vector<query> VQ;
int to[M];

long long can(DB r, bool CALC, DB &sum) {
	VQ.clear();
	for (int i = 0; i < n; i++) {
		PT tem[2];
		if (posCirLine(P, r, A[i], B[i], tem)) {
			DB ang[2];
			for (int j = 0; j < 2; j++) ang[j] = getAngle(tem[j] - P);
			if (ang[1] < ang[0]) swap(ang[0], ang[1]);
			VQ.push_back(query(ang[0], i, 1));
			VQ.push_back(query(ang[1], i, -1));
		}
	}
	sort(VQ.begin(), VQ.end());
	sum = 0;
	long long cnt = 0;
	BIT.clear();
	int now = 0, all = 0;
	vector<int> vec;
	for (auto &t : VQ) {
		if (t.sig == 1) {
			to[t.id] = now;
			BIT.add(now, 1);
			++all;
			if (CALC) vec.push_back(t.id);
		} else {
			cnt += (all - BIT.get(to[t.id]));
			BIT.add(to[t.id], -1);
			--all;
			if (CALC) {
				vector<int> tmp;
				while (vec.size() && vec.back() != t.id) {
					int a = t.id, b = vec.back();
					sum += dis(P - L[a].cross(L[b]));
					tmp.push_back(b);
					vec.pop_back();
				}
				if (vec.size()) vec.pop_back();
				while (tmp.size()) vec.push_back(tmp.back()), tmp.pop_back();
			}
		}
		++now;
	}
	return cnt;
}

int main() {
	scanf("%d", &n);
	P.in(); scanf("%d", &m);
	for (int i = 0; i < n; i++) {
		L[i].in();
		A[i] = PT(0, L[i].b);
		B[i] = PT(1, L[i].a + L[i].b);
	}
	DB st = 0, en = 1e10;
	DB ans;
	for (int times = 0; times < 60; times++) {
		DB md = (st + en) / 2;
		if (can(md, 0, ans) <= m) st = md;
		else en = md;
	}
	long long cnt = can(st, 1, ans);
	printf("%.10lf\n", ans + st * (m - cnt));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

using DB = double;
const DB EPS = 1e-8;
const DB PI = acos(-1);
const DB INF = 1e100;

inline DB sqr(DB x) {
	return x * x;
}

struct PT {
	DB x, y;
	PT (DB x = 0, DB y = 0) : x(x), y(y) {}
	void in() {
		scanf("%lf%lf", &x, &y);
		x /= 1000, y /= 1000;
	}
};

PT operator + (PT a, PT b) {
	return PT(a.x + b.x, a.y + b.y);
}

PT operator - (PT a, PT b) {
	return PT(a.x - b.x, a.y - b.y);
}

PT operator * (PT a, DB b) {
	return PT(a.x * b, a.y * b);
}

PT operator / (PT a, DB b) {
	return PT(a.x / b, a.y / b);
}

DB dis2(PT p) {
	return sqr(p.x) + sqr(p.y);
}

DB dis(PT p) {
	return sqrt(dis2(p));
}

DB scal(PT a, PT b) {
	return a.x * b.x + a.y * b.y;
}

DB getAngle(PT p) {
	return atan2(p.y, p.x);
}

int posCirLine(PT p, DB r, PT p1, PT p2, PT *q) {
	DB a = dis2(p1 - p2);
	DB b = scal(p - p1, p2 - p1);
	DB c = dis2(p - p1) - sqr(r);
	DB d2 = sqr(b) - a * c;
	if (d2 < -EPS) return 0;
	DB d = sqrt(fabs(d2));
	q[0] = p1 + (p2 - p1) * ((b + d) / a);
	q[1] = p1 + (p2 - p1) * ((b - d) / a);
	if (d2 < EPS) return 1;
	return 2;
}

const int N = 55000;
const int M = N + N;
PT A[N], B[N];

struct Line{
	DB a, b;
	void in() {
		scanf("%lf%lf", &a, &b);
		a /= 1000, b /= 1000;
	}
	Line (DB a = 0, DB b = 0) : a(a), b(b) {}
	PT cross(Line l) {
		if (fabs(a - l.a) < EPS) return PT(INF, INF);
		DB x = (l.b - b) / (a - l.a);
		DB y = a * x + b;
		return PT (x, y);
	}
} L[N];

int b[M];

void add(int idx, int v) {
	for (idx++; idx < M; idx += idx & -idx) b[idx] += v;
}

int get(int idx) {
	int ret = 0;
	for (idx++; idx; idx -= idx & -idx) ret += b[idx];
	return ret;
}

struct query{
	DB val;
	int id, sig;
	query(DB val = 0, int id = 0, int sig = 1) : val(val), id(id), sig(sig) {}
	bool operator <(const query &q) const {
		return val < q.val;
	}
};

int n, m;
PT P;
query VQ[M];
int to[M], id[M];
int vec[M], tmp[M];

long long can(DB r, bool CALC, DB &sum) {
	int vqn = 0;
	for (int i = 0; i < n; i++) {
		PT tem[2];
		if (posCirLine(P, r, A[i], B[i], tem)) {
			DB ang[2];
			for (int j = 0; j < 2; j++) ang[j] = getAngle(tem[j] - P);
			if (ang[1] < ang[0]) swap(ang[0], ang[1]);
			VQ[vqn++] = query(ang[0], i, 1);
			VQ[vqn++] = query(ang[1], i, -1);
		}
	}
	for (int i = 0; i < vqn; i++) id[i] = i;
	sort(id, id + vqn, [](int a, int b) { return VQ[a].val < VQ[b].val; });
	sum = 0;
	long long cnt = 0;
	memset(b, 0, sizeof b);
	int vn = 0;
	int now = 0, all = 0;
	for (int i = 0; i < vqn; i++) {
		query t = VQ[id[i]];
		if (t.sig == 1) {
			to[t.id] = now;
			add(now, 1);
			++all;
			if (CALC) vec[vn++] = t.id;
		} else {
			cnt += (all - get(to[t.id]));
			add(to[t.id], -1);
			--all;
			if (CALC) {
				int tn = 0;
				while (vn && vec[vn - 1] != t.id) {
					int a = t.id, b = vec[vn - 1];
					assert(fabs(L[a].a - L[b].a) > EPS);
					sum += dis(P - L[a].cross(L[b]));
					tmp[tn++] = b;
					vn--;
				}
				if (vn) vn--;
				while (tn) {
					vec[vn++] = tmp[tn - 1];
					--tn;
				}
			}
		}
		++now;
	}
	return cnt;
}

int main() {
//	freopen("in.txt", "r", stdin);
	scanf("%d", &n);
	P.in(); scanf("%d", &m);
	for (int i = 0; i < n; i++) {
		L[i].in();
		A[i] = PT(0, L[i].b);
		B[i] = PT(1, L[i].a + L[i].b);
	}
	DB st = 0, en = 3e9;
	DB ans;
	int now = 0;
	for (int times = 0; times < 48; times++) {
		DB md = (st + en) / 2;
		if (can(md, 0, ans) <= m) st = md;
		else en = md;
	}
	long long cnt = can(st, 1, ans);
	printf("%.10lf\n", ans + st * (m - cnt));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

using DB = double;
const DB EPS = 1e-8;
const DB PI = acos(-1);
const DB INF = 1e100;

inline DB sqr(DB x) {
	return x * x;
}

struct PT {
	DB x, y;
	PT (DB x = 0, DB y = 0) : x(x), y(y) {}
	void in() {
		scanf("%lf%lf", &x, &y);
		x /= 1000, y /= 1000;
	}
};

PT operator + (PT a, PT b) {
	return PT(a.x + b.x, a.y + b.y);
}

PT operator - (PT a, PT b) {
	return PT(a.x - b.x, a.y - b.y);
}

PT operator * (PT a, DB b) {
	return PT(a.x * b, a.y * b);
}

PT operator / (PT a, DB b) {
	return PT(a.x / b, a.y / b);
}

DB dis2(PT p) {
	return sqr(p.x) + sqr(p.y);
}

DB dis(PT p) {
	return sqrt(dis2(p));
}

DB scal(PT a, PT b) {
	return a.x * b.x + a.y * b.y;
}

DB getAngle(PT p) {
	return atan2(p.y, p.x);
}

int posCirLine(PT p, DB r, PT p1, PT p2, PT *q) {
	DB a = dis2(p1 - p2);
	DB b = scal(p - p1, p2 - p1);
	DB c = dis2(p - p1) - sqr(r);
	DB d2 = sqr(b) - a * c;
	if (d2 < -EPS) return 0;
	DB d = sqrt(fabs(d2));
	q[0] = p1 + (p2 - p1) * ((b + d) / a);
	q[1] = p1 + (p2 - p1) * ((b - d) / a);
	if (d2 < EPS) return 1;
	return 2;
}

const int N = 55000;
const int M = N + N;
PT A[N], B[N];

struct Line{
	DB a, b;
	void in() {
		scanf("%lf%lf", &a, &b);
		a /= 1000, b /= 1000;
	}
	Line (DB a = 0, DB b = 0) : a(a), b(b) {}
	PT cross(Line l) {
		if (fabs(a - l.a) < EPS) return PT(INF, INF);
		DB x = (l.b - b) / (a - l.a);
		DB y = a * x + b;
		return PT (x, y);
	}
} L[N];

int b[M];

void add(int idx, int v) {
	for (idx++; idx < M; idx += idx & -idx) b[idx] += v;
}

int get(int idx) {
	int ret = 0;
	for (idx++; idx; idx -= idx & -idx) ret += b[idx];
	return ret;
}

struct query{
	DB val;
	int id, sig;
	query(DB val = 0, int id = 0, int sig = 1) : val(val), id(id), sig(sig) {}
	bool operator <(const query &q) const {
		return val < q.val;
	}
};

int n, m;
PT P;
vector<query> VQ;
int to[M], id[M];
int vec[M], tmp[M];

long long can(DB r, bool CALC, DB &sum) {
	VQ.clear();
	for (int i = 0; i < n; i++) {
		PT tem[2];
		if (posCirLine(P, r, A[i], B[i], tem)) {
			DB ang[2];
			for (int j = 0; j < 2; j++) ang[j] = getAngle(tem[j] - P);
			if (ang[1] < ang[0]) swap(ang[0], ang[1]);
			VQ.push_back(query(ang[0], i, 1));
			VQ.push_back(query(ang[1], i, -1));
		}
	}
	for (int i = 0; i < VQ.size(); i++) id[i] = i;
	sort(id, id + VQ.size(), [](int a, int b) { return VQ[a].val < VQ[b].val; });
	sum = 0;
	long long cnt = 0;
	memset(b, 0, sizeof b);
	int vn = 0;
	int now = 0, all = 0;
	for (int i = 0; i < VQ.size(); i++) {
		query t = VQ[id[i]];
		if (t.sig == 1) {
			to[t.id] = now;
			add(now, 1);
			++all;
			if (CALC) vec[vn++] = t.id;
		} else {
			cnt += (all - get(to[t.id]));
			add(to[t.id], -1);
			--all;
			if (CALC) {
				int tn = 0;
				while (vn && vec[vn - 1] != t.id) {
					int a = t.id, b = vec[vn - 1];
					assert(fabs(L[a].a - L[b].a) > EPS);
					sum += dis(P - L[a].cross(L[b]));
					tmp[tn++] = b;
					vn--;
				}
				if (vn) vn--;
				while (tn) {
					vec[vn++] = tmp[tn - 1];
					--tn;
				}
			}
		}
		++now;
	}
	return cnt;
}

int main() {
//	freopen("in.txt", "r", stdin);
	scanf("%d", &n);
	P.in(); scanf("%d", &m);
	for (int i = 0; i < n; i++) {
		L[i].in();
		A[i] = PT(0, L[i].b);
		B[i] = PT(1, L[i].a + L[i].b);
	}
	DB st = 0, en = 1e10;
	DB ans;
	int now = 0;
	for (int times = 0; times < 60; times++) {
		DB md = (st + en) / 2;
		if (can(md, 0, ans) <= m) st = md;
		else en = md;
		if (clock() - now > 6.0 * CLOCKS_PER_SEC) {
			assert(times > 40);
		}
	}
	long long cnt = can(st, 1, ans);
	printf("%.10lf\n", ans + st * (m - cnt));
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

using DB = double;
const DB EPS = 1e-8;
const DB PI = acos(-1);

inline DB sqr(DB x) {
	return x * x;
}

struct PT {
	DB x, y;
	PT (DB x = 0, DB y = 0) : x(x), y(y) {}
	void in() {
		scanf("%lf%lf", &x, &y);
		x /= 1000, y /= 1000;
	}
};

PT operator + (PT a, PT b) {
	return PT(a.x + b.x, a.y + b.y);
}

PT operator - (PT a, PT b) {
	return PT(a.x - b.x, a.y - b.y);
}

PT operator * (PT a, DB b) {
	return PT(a.x * b, a.y * b);
}

PT operator / (PT a, DB b) {
	return PT(a.x / b, a.y / b);
}

DB dis2(PT p) {
	return sqr(p.x) + sqr(p.y);
}

DB dis(PT p) {
	return sqrt(dis2(p));
}

DB scal(PT a, PT b) {
	return a.x * b.x + a.y * b.y;
}

DB getAngle(PT p) {
	return atan2(p.y, p.x);
}

int posCirLine(PT p, DB r, PT p1, PT p2, PT *q) {
	DB a = dis2(p1 - p2);
	DB b = scal(p - p1, p2 - p1);
	DB c = dis2(p - p1) - sqr(r);
	DB d2 = sqr(b) - a * c;
	if (d2 < -EPS) return 0;
	DB d = sqrt(fabs(d2));
	q[0] = p1 + (p2 - p1) * ((b + d) / a);
	q[1] = p1 + (p2 - p1) * ((b - d) / a);
	if (d2 < EPS) return 1;
	return 2;
}

const int N = 55000;
const int M = N + N;
PT A[N], B[N];

struct Line{
	DB a, b;
	void in() {
		scanf("%lf%lf", &a, &b);
		a /= 1000, b /= 1000;
	}
	Line (DB a = 0, DB b = 0) : a(a), b(b) {}
	PT cross(Line l) {
		DB x = (l.b - b) / (a - l.a);
		DB y = a * x + b;
		return PT (x, y);
	}
} L[N];

int b[M];

void add(int idx, int v) {
	for (idx++; idx < M; idx += idx & -idx) b[idx] += v;
}

int get(int idx) {
	int ret = 0;
	for (idx++; idx; idx -= idx & -idx) ret += b[idx];
	return ret;
}

struct query{
	DB val;
	int id, sig;
	query(DB val = 0, int id = 0, int sig = 1) : val(val), id(id), sig(sig) {}
	bool operator <(const query &q) const {
		return val < q.val;
	}
};

int n, m;
PT P;
vector<query> VQ;
int to[M], id[M];
int vec[M], tmp[M];

long long can(DB r, bool CALC, DB &sum) {
	VQ.clear();
	for (int i = 0; i < n; i++) {
		PT tem[2];
		if (posCirLine(P, r, A[i], B[i], tem)) {
			DB ang[2];
			for (int j = 0; j < 2; j++) ang[j] = getAngle(tem[j] - P);
			if (ang[1] < ang[0]) swap(ang[0], ang[1]);
			VQ.push_back(query(ang[0], i, 1));
			VQ.push_back(query(ang[1], i, -1));
		}
	}
	for (int i = 0; i < VQ.size(); i++) id[i] = i;
	sort(id, id + VQ.size(), [](int a, int b) { return VQ[a].val < VQ[b].val; });
	sum = 0;
	long long cnt = 0;
	memset(b, 0, sizeof b);
	int vn = 0;
	int now = 0, all = 0;
	for (int i = 0; i < VQ.size(); i++) {
		query t = VQ[id[i]];
		if (t.sig == 1) {
			to[t.id] = now;
			add(now, 1);
			++all;
			if (CALC) vec[vn++] = t.id;
		} else {
			cnt += (all - get(to[t.id]));
			add(to[t.id], -1);
			--all;
			if (CALC) {
				int tn = 0;
				while (vn && vec[vn - 1] != t.id) {
					int a = t.id, b = vec[vn - 1];
					sum += dis(P - L[a].cross(L[b]));
					tmp[tn++] = b;
					vn--;
				}
				if (vn) vn--;
				while (tn) {
					vec[vn++] = tmp[tn - 1];
					--tn;
				}
			}
		}
		++now;
	}
	return cnt;
}

int main() {
//	freopen("in.txt", "r", stdin);
	scanf("%d", &n);
	P.in(); scanf("%d", &m);
	for (int i = 0; i < n; i++) {
		L[i].in();
		A[i] = PT(0, L[i].b);
		B[i] = PT(1, L[i].a + L[i].b);
	}
	DB st = 0, en = 1e10;
	DB ans;
	for (int times = 0; times < 50; times++) {
		DB md = (st + en) / 2;
		if (can(md, 0, ans) <= m) st = md;
		else en = md;
	}
	long long cnt = can(st, 1, ans);
	printf("%.10lf\n", ans + st * (m - cnt));
	return 0;
}