#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
#include<map>

using namespace std;

typedef long long ll;

//このnamespace内のMODという値を、問題の要求に応じて変更すること
namespace Mint {

	//このMODという値を、問題の要求に応じて変更すること
	const ll MOD = 998244353;

	template<ll Mod>
	struct Modint {
		ll val = 0;

		//コンストラクタ long long, 空, Modintを受け取れる
		Modint() = default;
		Modint(const Modint&) = default;
		Modint(ll _x) {
			val = _x >= 0 ? _x % Mod : ((_x % Mod) + Mod) % Mod;
		}

		//繰り返し二乗法、逆元　基本的に外部からいじるのやめたほうがよさそう。
		ll modpow(ll a, ll b) const {
			ll ret = 1, kakeru = a;
			while (b > 0) {
				if (b & 1)ret *= kakeru, ret %= Mod;
				kakeru *= kakeru, kakeru %= Mod;
				b >>= 1;
			}
			return ret;
		}
		Modint inv() const {
			return modpow((*this).val, MOD - 2);
		}

		//代入演算子　Modintとlong longの2通りある
		Modint operator= (const Modint& p) {
			val = p.val;
			return (*this);
		}

		//二項演算＋代入演算子　二項演算子、同値演算子はクラス外で定義する
		Modint& operator+= (const Modint& p) {
			val += p.val;
			if (val >= Mod)val -= Mod;
			return (*this);
		}
		Modint& operator-= (const Modint& p) {
			val -= p.val;
			if (val < 0)val += Mod;
			return (*this);
		}
		Modint& operator*= (const Modint& p) {
			val *= p.val;
			val %= Mod;
			return (*this);
		}
		Modint& operator/= (const Modint& p) {
			//なんか,p.inv()を使うとthisのポインターが変換できませんって出る
			//Modint tmp(p.inv());
			Modint tmp(modpow(p.val, MOD - 2));
			(*this) *= tmp;
			return (*this);
		}
	};

	//加算
	const Modint<MOD> operator+ (const Modint<MOD>& l, const Modint<MOD>& r) {
		Modint<MOD> tmp = l;
		tmp += r;
		return tmp;
	}
	const Modint<MOD> operator+ (const Modint<MOD>& l, const ll r) {
		Modint<MOD> tmp = l;
		tmp += Modint<MOD>(r);
		return tmp;
	}
	const Modint<MOD> operator+ (const ll l, const Modint<MOD>& r) {
		Modint<MOD> tmp = l;
		tmp += r;
		return tmp;
	}
	//減算
	const Modint<MOD> operator- (const Modint<MOD>& l, const Modint<MOD>& r) {
		Modint<MOD> tmp = l;
		tmp -= r;
		return tmp;
	}
	const Modint<MOD> operator- (const Modint<MOD>& l, const ll r) {
		Modint<MOD> tmp = l;
		tmp -= Modint<MOD>(r);
		return tmp;
	}
	const Modint<MOD> operator- (const ll l, const Modint<MOD>& r) {
		Modint<MOD> tmp = l;
		tmp -= r;
		return tmp;
	}
	//乗算
	const Modint<MOD> operator* (const Modint<MOD>& l, const Modint<MOD>& r) {
		Modint<MOD> tmp = l;
		tmp *= r;
		return tmp;
	}
	const Modint<MOD> operator* (const Modint<MOD>& l, const ll r) {
		Modint<MOD> tmp = l;
		tmp *= Modint<MOD>(r);
		return tmp;
	}
	const Modint<MOD> operator* (const ll l, const Modint<MOD>& r) {
		Modint<MOD> tmp = l;
		tmp *= r;
		return tmp;
	}
	//除算
	const Modint<MOD> operator/ (const Modint<MOD>& l, const Modint<MOD>& r) {
		Modint<MOD> tmp = l;
		tmp /= r;
		return tmp;
	}
	const Modint<MOD> operator/ (const Modint<MOD>& l, const ll r) {
		Modint<MOD> tmp = l;
		tmp /= Modint<MOD>(r);
		return tmp;
	}
	const Modint<MOD> operator/ (const ll l, const Modint<MOD>& r) {
		Modint<MOD> tmp = l;
		tmp /= r;
		return tmp;
	}
	//同値演算子
	const bool operator== (const Modint<MOD>& l, const Modint<MOD>& r) {
		return l.val == r.val;
	}
	const bool operator== (const Modint<MOD>& l, const ll r) {
		return l.val == r;
	}
	const bool operator== (const ll l, const Modint<MOD>& r) {
		return l == r.val;
	}
	const bool operator!= (const Modint<MOD>& l, const Modint<MOD>& r) {
		return !(l.val == r.val);
	}
	const bool operator!= (const Modint<MOD>& l, const ll r) {
		return !(l.val == r);
	}
	const bool operator!= (const ll l, const Modint<MOD>& r) {
		return !(l == r.val);
	}
	//istream ostream での入出力サポート
	std::ostream& operator<<(std::ostream& stream, const Modint<MOD>& p) {
		stream << p.val;
		return stream;
	}
	std::istream& operator >> (std::istream& stream, Modint<MOD>& p) {
		stream >> p.val;
		return stream;
	}
	//使う用の繰り返し二乗法 bはlong long に注意
	Modint<MOD> modpow(const Modint<MOD> a, ll b) {
		ll ret = 1, kakeru = a.val;
		while (b > 0) {
			if (b & 1)ret *= kakeru, ret %= MOD;
			kakeru *= kakeru, kakeru %= MOD;
			b >>= 1;
		}
		Modint<MOD> tmpret(ret);
		return tmpret;
	}
}

using namespace Mint;
using mint = Mint::Modint<MOD>;


//operation1 -> nodeのデータ同士の統合の演算
template <class Monoid> struct SegTree {
	int N;
	vector<Monoid> node;
	std::function<Monoid(Monoid, Monoid)> operation;
	Monoid unit;//単位元

	std::function<bool(Monoid, Monoid)> comp;
	Monoid not_find_sgn;

	SegTree(vector<Monoid>& data, std::function<Monoid(Monoid, Monoid)> op, Monoid U) {
		//データ　演算　単位元
		operation = op;
		unit = U;
		int size = data.size();
		N = 1;
		while (N < size)N <<= 1;
		node.resize(2 * N - 1, unit);

		for (int i = 0; i < size; i++) {
			node[i + N - 1] = data[i];
		}

		for (int i = N - 2; i >= 0; i--) {
			node[i] = operation(node[i * 2 + 1], node[i * 2 + 2]);
		}
	}

	SegTree() = default;

	void update(int pos, Monoid val) {
		pos += N - 1;
		node[pos] = val;
		while (pos > 0) {
			pos = (pos - 1) / 2;
			node[pos] = operation(node[pos * 2 + 1], node[pos * 2 + 2]);
		}
	}

	Monoid getval(int a, int b, int idx, int l, int r = -1) {
		//[a, b)を求める。　使い方はgetval(a, b, );
		if (r == -1)r = N;
		if (b <= l || r <= a)return unit;
		if (a <= l && r <= b)return node[idx];
		Monoid left = getval(a, b, idx * 2 + 1, l, (l + r) / 2);
		Monoid right = getval(a, b, idx * 2 + 2, (l + r) / 2, r);
		return operation(left, right);
	}

	Monoid getval(int a, int b) {
		//ラッパー。
		return getval(a, b, 0, 0, -1);
	}

};

int n;
pair<ll, ll> pt[200000];

map<pair<int, int>, ll> hidariue, hidarishita, migiue, migisita;

mint p2[200000 + 10];

int main() {
	p2[0] = 1;
	for (int i = 1; i <= 200000; i++)p2[i] = p2[i - 1] * 2;

	cin >> n;
	for (int i = 0; i < n; i++)cin >> pt[i].first >> pt[i].second;

	//x軸を圧縮する
	{
		vector<ll> tmp;
		for (int i = 0; i < n; i++)tmp.push_back(pt[i].first);
		sort(tmp.begin(), tmp.end());
		tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());
		for (int i = 0; i < n; i++) {
			pt[i].first = lower_bound(tmp.begin(), tmp.end(), pt[i].first) - tmp.begin();
		}
	}

	//y軸を圧縮する
	{
		vector<ll> tmp;
		for (int i = 0; i < n; i++)tmp.push_back(pt[i].second);
		sort(tmp.begin(), tmp.end());
		tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());
		for (int i = 0; i < n; i++) {
			pt[i].second = lower_bound(tmp.begin(), tmp.end(), pt[i].second) - tmp.begin();
		}
	}

	//xが小さい順に出して、y軸を転倒数のセグ木部分のようにする。
	vector<int> tmp(700000, 0);
	SegTree<int> st1(tmp, [](int a, int b) {return a + b; }, 0);
	
	sort(pt, pt + n, [](pair<int, int> l, pair<int, int> r) {
		if (l.second != r.second)return l.second < r.second;
		else return l.first < r.first;
	});
	for (int i = 0; i < n; i++) {
		hidarishita[pt[i]] += st1.getval(0, pt[i].first);
		migisita[pt[i]] += st1.getval(0, 650000) - st1.getval(0, pt[i].first);
		hidariue[pt[i]] -= st1.getval(0, pt[i].first);
		migiue[pt[i]] += -st1.getval(0, 650000) + st1.getval(0, pt[i].first);
		st1.update(pt[i].first, st1.getval(pt[i].first, pt[i].first + 1) + 1);
	}
	for (int i = 0; i < n; i++) {
		hidariue[pt[i]] += st1.getval(0, pt[i].first);
		migiue[pt[i]] += st1.getval(0, 650000) - st1.getval(0, pt[i].first + 1);
	}

	mint ans = 0;
	for (int i = 0; i < n; i++) {
		//左上と右下
		int A = hidariue[pt[i]], B = hidarishita[pt[i]], C = migiue[pt[i]], D = migisita[pt[i]];//自身を含む
		//自身を含まない
		ans += p2[n - 1];
		ans += (p2[A] - 1) * (p2[D] - 1) * p2[B + C];
		ans += (p2[B] - 1) * (p2[C] - 1) * p2[A + D];
		ans -= (p2[A] - 1) * (p2[B] - 1) * (p2[C] - 1) * (p2[D] - 1);
	}
	cout << ans << endl;
	return 0;
}

Measured memory_bytes: 67896