#include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::system_clock::now().time_since_epoch().count());
template <class T = int>
T __rand(T range = numeric_limits<T>::max()) {
  return (T)(rng() % range);
}
template <class T>
ostream& operator,(ostream& out, const T& thing) {
  return out << ", " << thing;
}
template <class U, class V>
ostream& operator<<(ostream& out, const pair<U, V>& p) {
  return (out << "(" << p.first, p.second) << ")";
}
template <class A, class B>
ostream& operator<<(ostream& out, const tuple<A, B>& t) {
  return (out << "(" << get<0>(t), get<1>(t)) << ")";
}
template <class A, class B, class C>
ostream& operator<<(ostream& out, const tuple<A, B, C>& t) {
  return (out << "(" << get<0>(t), get<1>(t), get<2>(t)) << ")";
}
template <class T>
ostream& operator<<(ostream& out, const vector<T>& container) {
  out << "{";
  if (((int)container.size())) out << container[0];
  for (int i = 0; i++ < ((int)container.size()) - 1;) out, container[i];
  return out << "}";
}
template <class x>
vector<typename x::value_type> $v(const x& a) {
  return vector<typename x::value_type>(a.begin(), a.end());
}
template <class u>
vector<typename iterator_traits<u>::value_type> $v(u a, u b) {
  return vector<typename iterator_traits<u>::value_type>(a, b);
}
const int maxn = 301010;
const int maxm = 22;
int n, m;
vector<int> add[maxn], rem[maxn];
vector<int> gr[maxn];
int comp_id[maxn], id[maxn];
vector<vector<vector<int>>> cnt;
void make_comp(int start) {
  if (((int)gr[start].size()) == 0) return;
  if (id[start] != -1) return;
  cnt.emplace_back();
  auto& cur_cnt = cnt.back();
  queue<int> qu;
  vector<int> nodes(1, start);
  id[start] = 0;
  comp_id[start] = ((int)cnt.size()) - 1;
  for (qu.push(start); qu.size(); qu.pop()) {
    int u = qu.front();
    for (auto v : gr[u]) {
      if (id[v] != -1) continue;
      id[v] = ((int)nodes.size());
      comp_id[v] = ((int)cnt.size()) - 1;
      nodes.push_back(v);
      qu.push(v);
    }
  }
  vector<int> adj_mask(((int)nodes.size()));
  for (int i = -1; ++i < ((int)nodes.size());) {
    auto& cur_mask = adj_mask[i];
    for (auto v : gr[nodes[i]]) cur_mask ^= 1 << id[v];
  }
  cur_cnt.assign(((int)nodes.size()), vector<int>(1 << ((int)nodes.size())));
  int max_mask = 0;
  function<void(int, int)> trans = [&](int u, int cur_mask) {
    if (u == ((int)nodes.size())) {
      cur_cnt[__builtin_popcount(cur_mask)][cur_mask] = 1;
      max_mask = max(max_mask, __builtin_popcount(cur_mask));
      return;
    }
    if (!(adj_mask[u] & cur_mask)) {
      trans(u + 1, cur_mask ^ (1 << u));
    }
    trans(u + 1, cur_mask);
  };
  trans(0, 0);
  cur_cnt.resize(max_mask + 1);
  for (int x = -1; ++x < ((int)cur_cnt.size());) {
    auto& sos = cur_cnt[x];
    for (int i = -1; ++i < ((int)nodes.size());)
      for (int mask = -1; ++mask < ((int)sos.size());)
        if ((mask >> i) & 1) sos[mask] += sos[mask ^ (1 << i)];
  };
}
int main(void) {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  for (int i = 0; i++ < n;) {
    int l, r;
    cin >> l >> r;
    add[l].push_back(i);
    rem[r + 1].push_back(i);
  }
  for (int i = -1; ++i < m;) {
    int u, v;
    cin >> u >> v;
    gr[u].push_back(v);
    gr[v].push_back(u);
  }
  fill(id, id + n + 10, -1);
  for (int i = 0; i++ < n;) make_comp(i);
  ;
  const long long mod = (long long)998244353;
  vector<long long> fac(n + 1, 0ll), ifac(n + 1, 1ll);
  fac[0] = 1;
  for (int i = 0; i++ < n;) fac[i] = fac[i - 1] * i % mod;
  for (int i = 0; i++ < n;) {
    long long exp = mod - 2;
    long long base = fac[i];
    for (; exp > 0; exp >>= 1) {
      if (exp & 1) (ifac[i] *= base) %= mod;
      (base *= base) %= mod;
    }
  }
  auto choose = [&](int x, int y) {
    return x >= y && y >= 0 ? fac[x] * ifac[y] % mod * ifac[x - y] % mod : 0ll;
  };
  vector<int> comp_mask(((int)cnt.size()));
  long long ans = 0;
  int rest = 0;
  for (int i = 0; i++ < n;) {
    ;
    for (auto x : add[i]) {
      if (id[x] != -1)
        comp_mask[comp_id[x]] ^= 1 << id[x];
      else
        ++rest;
    }
    for (auto x : rem[i]) {
      if (id[x] != -1)
        comp_mask[comp_id[x]] ^= 1 << id[x];
      else
        --rest;
    };
    vector<long long> cur_cnt(1, 1);
    for (int comp = -1; ++comp < ((int)cnt.size());) {
      vector<long long> cc(((int)cnt[comp].size()));
      for (int f = -1; ++f < ((int)cnt[comp].size());)
        cc[f] = cnt[comp][f][comp_mask[comp]];
      ;
      vector<long long> new_cnt(((int)cur_cnt.size()) + ((int)cc.size()) - 1);
      for (int u = -1; ++u < ((int)cur_cnt.size());) {
        for (int v = -1; ++v < ((int)cc.size());)
          (new_cnt[u + v] += cur_cnt[u] * cc[v]) %= mod;
      }
      cur_cnt = new_cnt;
    };
    long long cur_ans = 0;
    for (int f = -1; ++f < ((int)cur_cnt.size());) {
      (cur_ans += 1ll * cur_cnt[f] * choose(rest, i - f) % mod) %= mod;
    }
    (ans += cur_ans) %= mod;
  }
  cout << ans;
  return 0;
}
