#include"bits/stdc++.h"
using namespace std;
#define LL long long
#define PB push_back
#define MP make_pair
#define MOD 998244353

//累乗 O(log N)
long long power(long long x, long long N){
	if(N == 0) return 1LL;
	if(N == 1) return x;
	long long tmp = power(x, N/2);
	if(N%2 == 0) return tmp * tmp % MOD;
	else return tmp * tmp % MOD * x % MOD;
}

//RSQ
struct SegmentTree{
private:
	int N;
	vector<long long> node, lazy;
	vector<bool> lazyFlg;
	const long long DEFAULT = 0LL;
public:
	void init(int n){ //初期化 O(N)
		node.clear();
		lazy.clear();
		lazyFlg.clear();
		N = 1;
		while(N < n) N = (N<<1);
		for(int i=0; i<2*N-1; i++){
			node.push_back(DEFAULT);
			lazy.push_back(0LL);
			lazyFlg.push_back(false);
		}
	}
	void eval(int k, int l, int r){ //遅延評価 O(1)
		if(lazyFlg[k]){ //RUQ：下に更新クエリが溜まっていても加算クエリが溜まっていても上書き
			node[k] = lazy[k];
			if(r-l > 1){
				lazy[2*k+1] = lazy[k] / 2;
				lazyFlg[2*k+1] = true;
				lazy[2*k+2] = lazy[k] / 2;
				lazyFlg[2*k+2] = true;
			}
			lazy[k] = 0LL;
			lazyFlg[k] = false;
		}
		else{ //RAQ：下に更新クエリが溜まっていても加算クエリが溜まっていても加算
			node[k] += lazy[k];
			if(r-l > 1){
				lazy[2*k+1] += lazy[k] / 2;
				lazy[2*k+2] += lazy[k] / 2;
			}
			lazy[k] = 0LL;
		}
	}
	void update(int a, long long x){ //[a,a+1)の値を変更 O(log N)
		update(a, a+1, x);
	}
	void update(int a, int b, long long x, int k=0, int l=0, int r=-1){ //[a,b)の値を変更 O(log N)
		if(r == -1) r = N;
		eval(k, l, r);
		if(b <= l || r <= a) return; //交差する場合
		if(a <= l && r <= b){ //完全に含む場合
			lazy[k] = x * (r-l);
			lazyFlg[k] = true;
			eval(k, l, r);
		}
		else{
			update(a, b, x, 2*k+1, l, (l+r)/2);
			update(a, b, x, 2*k+2, (l+r)/2, r);
			node[k] = node[2*k+1] + node[2*k+2];
		}
	}
	void add(int a, long long x){ //[a,a+1)の値に加算 O(log N)
		add(a, a+1, x);
	}
	void add(int a, int b, long long x, int k=0, int l=0, int r=-1){ //[a,b)の値に加算 O(log N)
		if(r == -1) r = N;
		eval(k, l, r);
		if(b <= l || r <= a) return; //交差する場合
		if(a <= l && r <= b){ //完全に含む場合
			lazy[k] += x * (r-l);
			eval(k, l, r);
		}
		else{
			add(a, b, x, 2*k+1, l, (l+r)/2);
			add(a, b, x, 2*k+2, (l+r)/2, r);
			node[k] = node[2*k+1] + node[2*k+2];
		}
	}
	long long sum(int a, int b, int k=0, int l=0, int r=-1){ //[a,b)の和 O(log N)
		if(r == -1) r = N;
		if(b <= l || r <= a) return DEFAULT; //交差する場合
		eval(k, l, r);
		if(a <= l && r <= b) return node[k]; //完全に含む場合
		return sum(a, b, k*2+1, l, (l+r)/2) + sum(a, b, k*2+2, (l+r)/2, r);
	}
};

int N;
pair<int, int> P[200000];
vector<int> X, Y;
SegmentTree rsqL, rsqR;

LL queryL(int i, int j){
	return power(2, rsqL.sum(i, j))-1+MOD;
}

LL queryR(int i, int j){
	return power(2, rsqR.sum(i, j))-1+MOD;
}

int main(){
	scanf("%d", &N);
	for(int i=0; i<N; i++){
		scanf("%d%d", &P[i].first, &P[i].second);
		X.PB(P[i].first);
		Y.PB(P[i].second);
	}
	sort(X.begin(), X.end());
	sort(Y.begin(), Y.end());
	for(int i=0; i<N; i++){
		P[i].first = lower_bound(X.begin(), X.end(), P[i].first) - X.begin();
		P[i].second = lower_bound(Y.begin(), Y.end(), P[i].second) - Y.begin();
	}
	sort(P, P+N);
	rsqL.init(N);
	rsqR.init(N);
	rsqR.update(0, N, 1);
	
	LL ans = 0;
	for(int i=0; i<N; i++){
		rsqR.update(P[i].second, 0);

		LL ld = queryL(0, P[i].second);
		LL lu = queryL(P[i].second+1, N);
		LL rd = queryR(0, P[i].second);
		LL ru = queryR(P[i].second+1, N);

		// P exclusive (* 2 means the case inclusive)
		ans += ld * ru * 2;
		ans %= MOD;
		ans += ld * ru % MOD * lu * 2;
		ans %= MOD;
		ans += ld * ru % MOD * rd * 2;
		ans %= MOD;
		ans += ld * ru % MOD * lu % MOD * rd * 2;
		ans %= MOD;

		ans += lu * rd * 2;
		ans %= MOD;
		ans += lu * rd % MOD * ld * 2;
		ans %= MOD;
		ans += lu * rd % MOD * ru * 2;
		ans %= MOD;

		// P inclusive
		ans += ld;
		ans %= MOD;
		ans += lu;
		ans %= MOD;
		ans += rd;
		ans %= MOD;
		ans += ru;
		ans %= MOD;
		ans += ld * rd;
		ans %= MOD;
		ans += lu * ru;
		ans %= MOD;
		ans += ld * lu;
		ans %= MOD;
		ans += rd * ru;
		ans %= MOD;
		ans++;
		ans %= MOD;

		rsqL.update(P[i].second, 1);
	}
	printf("%lld\n", ans);
}

Measured memory_bytes: 22676