#include <bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimization("O3")
#pragma GCC optimization("unroll-loops")
using namespace std;
template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << "{" << p.first << "," << p.second << "}";
  return os;
}
const long long N = 2e6 + 5;
const long long oo = 998244353;
vector<long long> suru[N];
vector<long long> sesh[N];
vector<pair<long long, long long> > g[N];
long long u[N];
long long v[N];
long long m;
long long sz[N];
long long gtsz(long long mask) {
  vector<long long> x;
  for (long long i = 0; i < m; i++) {
    if (mask & 1) x.push_back(u[i]), x.push_back(v[i]);
    mask >>= 1;
  }
  sort(x.begin(), x.end());
  x.erase(unique(x.begin(), x.end()), x.end());
  return x.size();
}
long long totsz[50];
void calc(long long mask) {
  memset(totsz, 0, sizeof totsz);
  for (long long i = mask; i > 0; i = (i - 1) & mask) {
    totsz[sz[i]] += (__builtin_popcount(i) % 2 ? 1 : -1);
  }
}
long long fact[N];
long long fact_inv[N];
long long extended_euclidean(long long a, long long b, long long &x,
                             long long &y) {
  if (a == 0) {
    x = 0;
    y = 1;
    return b;
  }
  long long x1, y1;
  long long d = extended_euclidean(b % a, a, x1, y1);
  x = y1 - (b / a) * x1;
  y = x1;
  return d;
}
long long mod_inverse(long long a, long long m) {
  long long x, y;
  long long g = extended_euclidean(a, m, x, y);
  if (g != 1) {
    cout << "No solution!";
    return -1;
  } else {
    x = (x % m + m) % m;
    return x;
  }
}
long long ncr(long long n, long long r) {
  return fact[n] * fact_inv[n - r] % oo * fact_inv[r] % oo;
}
int32_t main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  fact[0] = 1;
  for (long long i = 1; i < N; i++) {
    fact[i] = (fact[i - 1] * i) % oo;
  }
  fact_inv[N - 1] = mod_inverse(fact[N - 1], oo);
  for (long long i = N - 2; i >= 0; i--) {
    fact_inv[i] = (fact_inv[i + 1] * (i + 1)) % oo;
  }
  assert(fact_inv[0] == 1);
  long long n;
  cin >> n >> m;
  for (long long i = 1; i <= n; i++) {
    long long l, r;
    cin >> l >> r;
    suru[l].push_back(i);
    sesh[r].push_back(i);
  }
  for (long long i = 0; i < m; i++) {
    cin >> u[i] >> v[i];
    g[u[i]].push_back({v[i], i});
    g[v[i]].push_back({u[i], i});
  }
  for (long long i = 0; i < (1 << m); i++) {
    sz[i] = gtsz(i);
  }
  set<long long> st;
  long long ans = 0;
  long long old = 0;
  for (long long i = 1; i <= n; i++) {
    for (long long u : suru[i]) st.insert(u);
    int mask = 0;
    for (int j = 0; j < m; j++)
      if (st.find(u[j]) != st.end() and st.find(v[j]) != st.end())
        mask |= 1 << j;
    if (mask != old) {
      old = mask;
      calc(mask);
    }
    long long nowsz = st.size();
    if (nowsz >= i) {
      ans = (ans + ncr(nowsz, i)) % oo;
      for (long long j = 1; j <= 2 * m and j <= i; j++) {
        ans = (ans - ncr(nowsz - j, i - j) * totsz[j] % oo) % oo;
      }
    }
    for (long long u : sesh[i]) {
      st.erase(u);
    }
  }
  ans = (ans + oo) % oo;
  cout << ans << "\n";
}
