#include "bits/stdc++.h"
using namespace std;
using ll     = long long;
using pii    = pair<int, int>;
using pll    = pair<ll, ll>;
using vi     = vector<int>;
using vl     = vector<ll>;
using vvi    = vector<vi>;
using vvl    = vector<vl>;
const ll INF = 1LL << 60;
const ll MOD = 998244353;
template <class T>
bool chmax(T &a, const T &b) {
    return (a < b) ? (a = b, 1) : 0;
}
template <class T>
bool chmin(T &a, const T &b) {
    return (b < a) ? (a = b, 1) : 0;
}
template <class C>
void print(const C &c, std::ostream &os = std::cout) {
    std::copy(std::begin(c), std::end(c), std::ostream_iterator<typename C::value_type>(os, " "));
    os << std::endl;
}

// mod int struct
// original : https://github.com/beet-aizu/library/blob/master/mod/mint.cpp

struct mint {
    ll v;
    ll mod;
    mint() : v(0) {}
    mint(signed v, ll mod = MOD) : v(v), mod(mod) {}
    mint(ll t, ll mod = MOD) : mod(mod) {
        v = t % mod;
        if (v < 0)
            v += mod;
    }

    mint pow(ll k) {
        mint res(1), tmp(v);
        while (k) {
            if (k & 1)
                res *= tmp;
            tmp *= tmp;
            k >>= 1;
        }
        return res;
    }

    static mint add_identity() { return mint(0); }
    static mint mul_identity() { return mint(1); }

    mint inv() { return pow(mod - 2); }

    mint &operator+=(mint a) {
        v += a.v;
        if (v >= mod)
            v -= mod;
        return *this;
    }
    mint &operator-=(mint a) {
        v += mod - a.v;
        if (v >= mod)
            v -= mod;
        return *this;
    }
    mint &operator*=(mint a) {
        v = 1LL * v * a.v % mod;
        return *this;
    }
    mint &operator/=(mint a) { return (*this) *= a.inv(); }

    mint operator+(mint a) const { return mint(v) += a; };
    mint operator-(mint a) const { return mint(v) -= a; };
    mint operator*(mint a) const { return mint(v) *= a; };
    mint operator/(mint a) const { return mint(v) /= a; };

    mint operator-() const { return v ? mint(mod - v) : mint(v); }

    bool operator==(const mint a) const { return v == a.v; }
    bool operator!=(const mint a) const { return v != a.v; }
    bool operator<(const mint a) const { return v < a.v; }

    // find x s.t. a^x = b
    static ll log(ll a, ll b) {
        const ll sq = 40000;
        unordered_map<ll, ll> dp;
        dp.reserve(sq);
        mint res(1);
        for (int r = 0; r < sq; r++) {
            if (!dp.count(res.v))
                dp[res.v] = r;
            res *= a;
        }
        mint p = mint(a).inv().pow(sq);
        res    = b;
        for (int q = 0; q <= MOD / sq + 1; q++) {
            if (dp.count(res.v)) {
                ll idx = q * sq + dp[res.v];
                if (idx > 0)
                    return idx;
            }
            res *= p;
        }
        assert(0);
        return ll(-1);
    }

    static mint comb(long long n, int k) {
        mint num(1), dom(1);
        for (int i = 0; i < k; i++) {
            num *= mint(n - i);
            dom *= mint(i + 1);
        }
        return num / dom;
    }
};
ostream &operator<<(ostream &os, mint m) {
    os << m.v;
    return os;
}

// 0-indexed bottom up Segment Tree
// UNIT is the identity element of operation func
template <typename T = int>
struct SegmentTree {
    using F = function<T(T, T)>;
    int n;
    vector<T> dat;
    F func;
    T UNIT;

    SegmentTree(int n_, F func_, T UNIT_) : func(func_), UNIT(UNIT_) {
        n = 1;
        // full binary tree: num of leaves = n = 2^k >= n_
        while (n < n_)
            n *= 2;
        dat.assign(2 * n - 1, UNIT);
    }
    SegmentTree(vector<T> v_, F func_, T UNIT_) : func(func_), UNIT(UNIT_) {
        n      = 1;
        int nv = v_.size();
        while (n < nv)
            n *= 2;
        dat.assign(2 * n - 1, UNIT);
        for (int i = 0; i < nv; ++i) {
            dat[n - 1 + i] = v_[i];
        }
        for (int i = n - 2; i >= 0; --i) {
            dat[i] = func(dat[2 * i + 1], dat[2 * i + 2]);
        }
    }
    void update(int k, T a) {
        // leaves are at index n-1 to 2*n-2
        k += n - 1;
        dat[k] = a;
        while (k > 0) {
            // k -> parent node
            k = (k - 1) / 2;
            // func(child nodes)
            dat[k] = func(dat[2 * k + 1], dat[2 * k + 2]);
        }
    }
    // get result of func() in [l, r)
    T query(int l, int r) {
        l += n - 1;
        r += n - 1;
        T ret = UNIT;
        while (l < r) {
            if ((l & 1) == 0)
                ret = func(ret, dat[l]);
            if ((r & 1) == 0)
                ret = func(ret, dat[r - 1]);
            l = l / 2;
            r = (r - 1) / 2;
        }
        return ret;
    }
};

int main() {
    int n;
    cin >> n;
    vl x(n), y(n);
    map<ll, int> mx, my;
    for (int i = 0; i < n; ++i) {
        cin >> x[i] >> y[i];
        mx[x[i]] = 0;
        my[y[i]] = 0;
    }
    int idx = 0;
    for (auto &p : mx) {
        p.second = idx++;
    }
    idx = 0;
    for (auto &p : my) {
        p.second = idx++;
    }
    vector<pii> xy(n);
    for (int i = 0; i < n; ++i) {
        xy[i] = {mx[x[i]], my[y[i]]};
    }
    sort(xy.begin(), xy.end());
    auto f = [](int l, int r) { return l + r; };
    SegmentTree<int> sgl(n, f, 0), sgr(n, f, 0);
    vi ul(n, 0), dl(n, 0), ur(n, 0), dr(n, 0);
    for (int i = 0; i < n; ++i) {
        ul[i] = sgl.query(xy[i].second, n + 1);
        dl[i] = sgl.query(0, xy[i].second);
        sgl.update(xy[i].second, 1);
    }
    for (int i = n - 1; i >= 0; --i) {
        ur[i] = sgr.query(xy[i].second, n + 1);
        dr[i] = sgr.query(0, xy[i].second);
        sgr.update(xy[i].second, 1);
    }
    mint ret = 0;
    for (int i = 0; i < n; ++i) {
        mint temp = mint(2).pow(n) - 1;
        temp -= mint(2).pow(ul[i] + dl[i]) - 1;
        temp -= mint(2).pow(ur[i] + dr[i]) - 1;
        temp -= mint(2).pow(ul[i] + ur[i]) - 1;
        temp -= mint(2).pow(dl[i] + dr[i]) - 1;
        temp += mint(2).pow(dl[i]) - 1;
        temp += mint(2).pow(dr[i]) - 1;
        temp += mint(2).pow(ul[i]) - 1;
        temp += mint(2).pow(ur[i]) - 1;
        ret += temp;
    }
    cout << ret << "\n";
    return 0;
}

Measured memory_bytes: 37120