#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <string>
#include <sstream>
#include <complex>
#include <vector>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <random>

using namespace std;
 
#define mod 998244353
#define FOR(x,to) for(int x=0;x<(to);x++)
#define FORR(x,arr) for(auto& x:arr)
#define ALL(a) (a.begin()),(a.end())
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
#define long long long
inline int rei(){int x;cin>>x;return x;}
inline long rel(){long x;cin>>x;return x;}
inline string res(){string x;cin>>x;return x;}
//------------------------------------------------------- 
class Monoid {
public:
    using t = int;
    static t id() {
        return 0;
    }
    static t op(const t& l, const t& r) {
        return l+r;
    }
};
template< typename M >
class SegmentTree {
	using T = typename M::t;
	const int n;
	vector<T> data;
	int size(int n_) {
        int res = 1;
        while (res <= n_) {
			res <<= 1;
		}
        return res;
    }
	public:
    SegmentTree(int n_)
        : n(size(n_)), data(n * 2, M::id()) {}
    SegmentTree(int n_, T v)
        : n(size(n_)), data(n * 2, v) {}
    SegmentTree(const vector<T>& data_)
        : n(size(data_.size())), data(n * 2, M::id()) {
            init(data_);
    }
    void init() {
        for (int i = n - 1; i >= 1; i--) data[i] = M::op(data[i * 2], data[i * 2 + 1]);
    }
    void init(const vector<T>& data_) {
        for (int i = 0; i < (int)data_.size(); i++) data[i + n] = data_[i];
        init();
    }
  	void Update(int k,const T x){
    	k += n;
    	data[k] = x;
    	while(k >>= 1){
      		data[k] = M::op(data[2*k+0],data[2*k+1]);
    	}
  	}
	//[a,b)
  	T Query(int a,int b){
    	T L = M::id(), R = M::id();
    	for(a += n,b += n;a < b;a >>= 1,b >>= 1){
      		if(a & 1) L = M::op(L,data[a++]);
      		if(b & 1) R = M::op(data[--b],R);
    	}
    	return M::op(L,R);
  	}
	T Query(int a){
    	return data[a+n];
  	}
	//[0,bc]がFを満たす最小のbc(>=0)ないなら-1
	int MinSearch(function<bool(T)> F){
		if(!F(data[1])){
			return -1;
		}
    	T L = M::id();
		int a = 1;
		while(a < n){
			if(!F(M::op(L,data[a << 1]))){
				L = M::op(L,data[a << 1]);
				a = (a << 1) + 1;
			}
			else{
				a <<= 1;
			}
		}
    	return a-n;
  	}
	//[v,bc]がFを満たす最小のbc(>=v)ないなら-1
	int MinSearch(int v,function<bool(T)> F){
		int a = v+n;
		T L = data[a];
		if(F(L)){
			return v;
		}
		while(a > 1){
			if((a & 1) == 0){
				if(F(M::op(L,data[a+1]))){
					a++;
					break;
				}
				L = M::op(L,data[a+1]);
			}
			a >>= 1;
		}
		if(a == 1){
			return -1;
		}
		while(a < n){
			if(!F(M::op(L,data[a << 1]))){
				L = M::op(L,data[a << 1]);
				a = (a << 1) + 1;
			}
			else{
				a <<= 1;
			}
		}
    	return a-n;
  	}
};
pair<int,int> XP[200000];
pair<int,int> YP[200000];
int X[200000];
int Y[200000];
long Pow[200001];
void Calc(){
	int N = rei();
	for(int i=0;i<N;i++){
		int xi = rei();
		int yi = rei();
		XP[i] = {xi,i};
		YP[i] = {yi,i};
	}
	sort(XP,XP+N);
	sort(YP,YP+N);
	for(int i=0;i<N;i++){
		X[XP[i].second] = i;
		Y[YP[i].second] = i;
	}
	Pow[0] = 1;
	for(int i=1;i<=N;i++){
		Pow[i] = Pow[i-1] * 2 % mod;
	}
	long ans = 0;
	SegmentTree<Monoid> Seg1(N);
	for(int i=0;i<N;i++){
		int p = XP[i].second;
		int U = Seg1.Query(0,Y[p]);
		int D = Seg1.Query(Y[p]+1,N);
		Seg1.Update(Y[p],1);
		ans += Pow[N];
		ans += mod-Pow[U+D];
		ans += mod-Pow[N-U-D-1];
		ans += mod-Pow[Y[p]];
		ans += mod-Pow[N-1-Y[p]];
		ans += Pow[U]+Pow[D];
	}
	SegmentTree<Monoid> Seg2(N);
	for(int i=N-1;i>=0;i--){
		int p = XP[i].second;
		int U = Seg2.Query(0,Y[p]);
		int D = Seg2.Query(Y[p]+1,N);
		Seg2.Update(Y[p],1);
		ans += Pow[U]+Pow[D];
	}
	ans += mod - N;
	ans %= mod;
	cout << ans << endl;
}
int main(int argc,char** argv){
	ios::sync_with_stdio(false), cin.tie(0);
	cout.tie(0); Calc(); return 0;
}

Measured memory_bytes: 10624