#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define fr(n) for(int i=0;i<n;i++)
int n, m;
// segment tree (max) storing indices (0-based) or -1
struct SegTree {
int n;
vector<int> st;
SegTree(int _n=0){ init(_n); }
void init(int _n){
n = _n;
st.assign(4*n, -1);
}
void upd(int p, int val){ upd(1,0,n-1,p,val); }
void upd(int node,int l,int r,int p,int val){
if(l==r){ st[node]=max(st[node], val); return; }
int mid=(l+r)/2;
if(p<=mid) upd(node*2,l,mid,p,val);
else upd(node*2+1,mid+1,r,p,val);
st[node]=max(st[node*2], st[node*2+1]);
}
int query(int L,int R){
if(L>R) return -1;
return query(1,0,n-1,L,R);
}
int query(int node,int l,int r,int L,int R){
if(R<l || r<L) return -1;
if(L<=l && r<=R) return st[node];
int mid=(l+r)/2;
return max(query(node*2,l,mid,L,R), query(node*2+1,mid+1,r,L,R));
}
};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
if(!(cin>>n>>m)) return 0;
vector<pair<ll,ll>> v(n);
for(int i=0;i<n;i++){
ll x,y; cin>>x>>y;
v[i] = {y,x}; // ordenar por y desc
}
sort(v.begin(), v.end(), greater<>());
vector<ll> a(n);
for(int i=0;i<n;i++) a[i] = v[i].second;
vector<ll> p(m);
for(int i=0;i<m;i++) cin>>p[i];
// compresión: juntar a y p, ordenar asc y map a 0..c-1
vector<ll> allv = a;
allv.insert(allv.end(), p.begin(), p.end());
sort(allv.begin(), allv.end());
allv.erase(unique(allv.begin(), allv.end()), allv.end());
int c = (int)allv.size();
auto comp = [&](ll x){ return (int)(lower_bound(allv.begin(), allv.end(), x) - allv.begin()); };
for(int i=0;i<n;i++) a[i] = comp(a[i]);
for(int i=0;i<m;i++) p[i] = comp(p[i]);
// p_val: p ordenado en orden descendente (valores comprimidos)
vector<int> p_val(m);
for(int i=0;i<m;i++) p_val[i] = (int)p[i];
sort(p_val.begin(), p_val.end(), greater<int>());
// segment tree sobre rango de valores comprimidos [0..c-1]
SegTree st(c);
int res = 0;
// recorremos a (ya ordenado por y desc)
for(int i=0;i<n && res < m;i++){
int ai = (int)a[i]; // valor comprimido en [0..c-1]
// buscamos en p_val el mayor índice j tal que p_val[j] >= ai
// p_val es descendente, queremos el rightmost index with p_val[j] >= ai
int lo = 0, hi = m-1, pos = -1;
while(lo <= hi){
int mid = (lo + hi) >> 1;
if(p_val[mid] >= ai){
pos = mid;
lo = mid + 1;
} else hi = mid - 1;
}
if(pos == -1) continue; // no hay p >= ai
// consultamos el árbol en el rango [ai, c-1] para obtener el mejor índice ya guardado
int q = st.query(ai, c-1); // q es índice 0-based en p_val o -1
// si no hay nada guardado, podemos usar pos (el mejor disponible)
int useIdx = max(q, pos);
// pero solo actualizamos si p_val[useIdx] >= ai (debería ser cierto)
if(useIdx != -1 && p_val[useIdx] >= ai){
// guardamos useIdx en la posición ai (podemos guardar el mejor índice alcanzable desde ai)
st.upd(ai, useIdx);
res = max(res, useIdx + 1); // cantidad = índice+1
}
}
cout << res << "\n";
return 0;
}