//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("no-stack-protector")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,popcnt,abm,mmx,tune=native")
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <stdio.h>
#include <cstdio>
#include <math.h>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
#include <deque>
#include <random>
#include <iomanip>
#include <bitset>
 
using namespace std;
                        
template<typename T> void uin(T &a, T b) {
    if (b < a) {
        a = b;
    }
}
                        
template<typename T> void uax(T &a, T b) {
    if (b > a) {
        a = b;
    }
}

#define int long long
#define ghost signed
#define left left228
#define right right228
#define complex complex228
#define count count228
#define sin sin228
#define list list228

const int N = 228228;
const int MOD = 998244353;

int mod(int x) {
	x %= MOD; if (x < 0) x += MOD;
	return x;
}

int fp(int a, int b) {
	int res = 1;
	while(b) {
		if (b & 1) res = mod(res * a);
		a = mod(a * a), b >>= 1;
	}
	return res;
}

struct node
{
	int sum;
	int l, r;
	node() {sum = l = r = 0;}
};

vector< node > d;
int ptr = 0;
int nn() {
	d.push_back(node());
	return ptr++;
}
int build(int l, int r) {
	int v = nn();
	if (l == r) return v;
	int m = (l + r) >> 1;
	d[v].l = build(l, m);
	d[v].r = build(m + 1, r);
	return v;
}
int inc(int v, int i, int l, int r) {
	if (l == r) {
		int kek = nn();
		d[kek].sum = d[v].sum + 1;
		return kek;
	}
	int root = nn();
	d[root].l = d[v].l, d[root].r = d[v].r;
	int m = (l + r) >> 1;
	if (i <= m) d[root].l = inc(d[v].l, i, l, m);
	else d[root].r = inc(d[v].r, i, m + 1, r);
	d[root].sum = d[d[root].l].sum + d[d[root].r].sum;
	return root;
}
int get(int v, int l, int r, int vl, int vr) {
	if (l > r || vl > r || vr < l) return 0;
	if (l <= vl && vr <= r) return d[v].sum;
	int vm = (vl + vr) >> 1;
	return get(d[v].l, l, r, vl, vm) + get(d[v].r, l, r, vm + 1, vr);
}
int tree[N], x[N], y[N];
vector<int> crdy[N];

ghost main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
	int n;
	cin >> n;
	vector<int> xx, yy;
	for (int i = 1; i <= n; ++i) {
		cin >> x[i] >> y[i];
		xx.push_back(x[i]), yy.push_back(y[i]);
	}
	sort(xx.begin(), xx.end()), xx.erase(unique(xx.begin(), xx.end()), xx.end());
	sort(yy.begin(), yy.end()), yy.erase(unique(yy.begin(), yy.end()), yy.end());
	int sx = (int)xx.size(), sy = (int)yy.size();
	for (int i = 1; i <= n; ++i) {
		x[i] = lower_bound(xx.begin(), xx.end(), x[i]) - xx.begin() + 1;
		y[i] = lower_bound(yy.begin(), yy.end(), y[i]) - yy.begin() + 1;
		crdy[x[i]].push_back(y[i]);
	}
	tree[0] = build(1, sy);
	for (int i = 1; i <= sx; ++i) {
		tree[i] = tree[i - 1];
		for (int j : crdy[i]) {
			tree[i] = inc(tree[i], j, 1, sy);
		}
	}
	int res = 0;
	for (int i = 1; i <= n; ++i) {
		int A = get(tree[x[i] - 1], 1, y[i] - 1, 1, sy);
		int B = get(tree[x[i] - 1], 1, sy, 1, sy) - A;
		int D = get(tree[sx], 1, y[i] - 1, 1, sy) - get(tree[x[i]], 1, y[i] - 1, 1, sy);
		int C = get(tree[sx], 1, sy, 1, sy) - get(tree[x[i]], 1, sy, 1, sy) - D;
		vector<int> v;
		v.push_back(A), v.push_back(B), v.push_back(C), v.push_back(D);
		int cur = fp(2, n - 1) - 1;
		for (int a : v) {
			int menos = fp(2, a) - 1;
			cur = mod(cur - menos);
		}
		for (int j = 0; j < 4; ++j) {
			int a = v[j], b = v[(j + 1) % 4];
			int menos = mod(fp(2, a + b) - 1 - (fp(2, a) - 1) - (fp(2, b) - 1));
			cur = mod(cur - menos);
		}
		res = mod(res + cur);
		res = mod(res + fp(2, n - 1));
	}
	cout << res << '\n';
    return 0;
} // kek ;
// Ого! Кажетсья это $#@!

Measured memory_bytes: 120912