#include <bits/stdc++.h>
using namespace std;
namespace modular {
template <typename>
struct is_modular : std::false_type {};
template <int M>
struct static_mint {
  static_assert(0 < M, "Module must be positive");
  using mint = static_mint;
  constexpr static int get_mod() { return M; }
  int val;
  static_mint() : val() {}
  static_mint(long long x) : val(x % M) {
    if (val < 0) val += M;
  }
  mint pow(long long n) const {
    mint ans = 1, x(*this);
    while (n) {
      if (n & 1) ans *= x;
      x *= x;
      n /= 2;
    }
    return ans;
  }
  mint inv() const { return pow(M - 2); }
  friend mint pow(const mint &m, long long n) { return m.pow(n); }
  friend mint inv(const mint &m) { return m.inv(); }
  mint operator+() const {
    mint m;
    m.val = val;
    return m;
  }
  mint operator-() const {
    mint m;
    m.val = M - val;
    return m;
  }
  mint &operator+=(const mint &m) {
    if ((val += m.val) >= M) val -= M;
    return *this;
  }
  mint &operator-=(const mint &m) {
    if ((val -= m.val) < 0) val += M;
    return *this;
  }
  mint &operator*=(const mint &m) {
    val = (long long)val * m.val % M;
    return *this;
  }
  mint &operator/=(const mint &m) {
    val = (long long)val * m.inv().val % M;
    return *this;
  }
  friend mint operator+(const mint &lhs, const mint &rhs) {
    return mint(lhs) += rhs;
  }
  friend mint operator-(const mint &lhs, const mint &rhs) {
    return mint(lhs) -= rhs;
  }
  friend mint operator*(const mint &lhs, const mint &rhs) {
    return mint(lhs) *= rhs;
  }
  friend mint operator/(const mint &lhs, const mint &rhs) {
    return mint(lhs) /= rhs;
  }
  friend bool operator==(const mint &lhs, const mint &rhs) {
    return lhs.val == rhs.val;
  }
  friend bool operator!=(const mint &lhs, const mint &rhs) {
    return lhs.val != rhs.val;
  }
  mint &operator++() { return *this += 1; }
  mint &operator--() { return *this -= 1; }
  mint operator++(int) {
    mint result(*this);
    *this += 1;
    return result;
  }
  mint operator--(int) {
    mint result(*this);
    *this -= 1;
    return result;
  }
  template <typename T>
  explicit operator T() const {
    return T(val);
  }
  friend std::ostream &operator<<(std::ostream &os, const mint &m) {
    return os << m.val;
  }
  friend std::istream &operator>>(std::istream &is, mint &m) {
    long long x;
    is >> x;
    m = x;
    return is;
  }
};
template <int M>
struct is_modular<static_mint<M>> : std::true_type {};
struct dynamic_mint {
  static int M;
  static void set_mod(int m) {
    assert(0 < m);
    M = m;
  }
  static int get_mod() { return M; }
  using mint = dynamic_mint;
  int val;
  dynamic_mint() : val() {}
  dynamic_mint(long long x) : val(x % M) {
    if (val < 0) {
      val += M;
    }
  }
  mint pow(long long n) const {
    mint ans = 1, x(*this);
    while (n) {
      if (n & 1) ans *= x;
      x *= x;
      n /= 2;
    }
    return ans;
  }
  mint inv() const { return pow(M - 2); }
  friend mint pow(const mint &m, long long n) { return m.pow(n); }
  friend mint inv(const mint &m) { return m.inv(); }
  mint operator+() const {
    mint m;
    m.val = val;
    return m;
  }
  mint operator-() const {
    mint m;
    m.val = M - val;
    return m;
  }
  mint &operator+=(const mint &m) {
    if ((val += m.val) >= M) val -= M;
    return *this;
  }
  mint &operator-=(const mint &m) {
    if ((val -= m.val) < 0) val += M;
    return *this;
  }
  mint &operator*=(const mint &m) {
    val = (long long)val * m.val % M;
    return *this;
  }
  mint &operator/=(const mint &m) {
    val = (long long)val * m.inv().val % M;
    return *this;
  }
  friend mint operator+(const mint &lhs, const mint &rhs) {
    return mint(lhs) += rhs;
  }
  friend mint operator-(const mint &lhs, const mint &rhs) {
    return mint(lhs) -= rhs;
  }
  friend mint operator*(const mint &lhs, const mint &rhs) {
    return mint(lhs) *= rhs;
  }
  friend mint operator/(const mint &lhs, const mint &rhs) {
    return mint(lhs) /= rhs;
  }
  friend bool operator==(const mint &lhs, const mint &rhs) {
    return lhs.val == rhs.val;
  }
  friend bool operator!=(const mint &lhs, const mint &rhs) {
    return lhs.val != rhs.val;
  }
  mint &operator++() { return *this += 1; }
  mint &operator--() { return *this -= 1; }
  mint operator++(int) {
    mint result(*this);
    *this += 1;
    return result;
  }
  mint operator--(int) {
    mint result(*this);
    *this -= 1;
    return result;
  }
  template <typename T>
  explicit operator T() const {
    return T(val);
  }
  friend std::ostream &operator<<(std::ostream &os, const mint &m) {
    return os << m.val;
  }
  friend std::istream &operator>>(std::istream &is, mint &m) {
    long long x;
    is >> x;
    m = x;
    return is;
  }
};
int dynamic_mint::M;
template <>
struct is_modular<dynamic_mint> : std::true_type {};
}  // namespace modular
constexpr int N = 300000;
using mint = modular::static_mint<998244353>;
mint fact[N + 1], inv[N + 1];
mint choose(int n, int k) {
  if (0 <= n && 0 <= k && k <= n) {
    return fact[n] * inv[k] * inv[n - k];
  }
  return 0;
}
void zeta_transform(int n, vector<mint> &f) {
  for (int i = 0; i < n; i++) {
    for (int mask = 0; mask < (1 << n); mask++) {
      if (mask & (1 << i)) {
        f[mask] += f[mask ^ (1 << i)];
      }
    }
  }
}
int n, m, id[N + 1], p[N + 1], cur_mask[N + 1];
bitset<N + 1> visited;
vector<int> leaders, add[N + 1], rem[N + 1], g[N + 1], v[N + 1];
vector<vector<mint>> f[20];
vector<bool> ok[20];
void dfs(int x) {
  v[leaders.back()].push_back(x);
  visited[x] = true;
  for (int i : g[x]) {
    if (!visited[i]) {
      dfs(i);
    }
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  fact[0] = 1, inv[0] = 1;
  for (int i = 1; i <= N; i++) {
    fact[i] = i * fact[i - 1];
    inv[i] = fact[i].inv();
  }
  cin >> n >> m;
  for (int i = 1, l, r; i <= n; i++) {
    cin >> l >> r;
    add[l].push_back(i);
    rem[r].push_back(i);
  }
  for (int i = 0, a, b; i < m; i++) {
    cin >> a >> b;
    g[a].push_back(b);
    g[b].push_back(a);
  }
  for (int i = 1; i <= n; i++) {
    if (!g[i].empty() && !visited[i]) {
      int li = (int)leaders.size();
      leaders.push_back(i);
      dfs(i);
      int sz = int(v[i].size());
      for (int j = 0; j < sz; j++) {
        p[v[i][j]] = i;
        id[v[i][j]] = j;
      }
      ok[li].assign(1 << sz, true);
      f[li].assign(sz + 1, vector<mint>(1 << sz));
      for (int mask = 0; mask < (1 << sz); mask++) {
        int pop = 0;
        for (int j = 0; j < sz; j++) {
          if (mask & (1 << j)) {
            for (int x : g[v[i][j]]) {
              if (mask & (1 << id[x])) {
                ok[li][mask] = false;
              }
            }
            pop += 1;
          }
        }
        if (ok[li][mask]) {
          f[li][pop][mask] = 1;
        }
      }
      for (int j = 1; j <= sz; j++) {
        zeta_transform(sz, f[li][j]);
      }
    }
  }
  int ones = 0;
  mint ans = 0;
  for (int i = 1; i <= n; i++) {
    for (int x : add[i]) {
      if (g[x].empty()) {
        ones += 1;
      } else {
        cur_mask[p[x]] ^= (1 << id[x]);
      }
    }
    vector<mint> dp(41);
    dp[0] = 1;
    for (int li = 0; li < leaders.size(); li++) {
      int l = leaders[li];
      for (int k = 40; k >= 0; k--) {
        if (dp[k]) {
          for (int j = 1; j <= int(v[l].size()) && k + j <= 40; j++) {
            dp[k + j] += dp[k] * f[li][j][cur_mask[l]];
          }
        }
      }
    }
    for (int j = 0; j <= 40; j++) {
      ans += choose(ones, i - j) * dp[j];
    }
    for (int x : rem[i]) {
      if (g[x].empty()) {
        ones -= 1;
      } else {
        cur_mask[p[x]] ^= (1 << id[x]);
      }
    }
  }
  cout << ans << '\n';
  return 0;
}
