제출 #87087

#제출 시각아이디문제언어결과실행 시간메모리
87087JustInCasePort Facility (JOI17_port_facility)C++17
100 / 100
5400 ms638972 KiB
#include <bits/stdc++.h>

const int32_t MAX_N = 1e6;
const int32_t INF = 2e9;
const int32_t MOD = 1e9 + 7;

class SegmentTree {
private:
	bool isMax;
	int32_t treeSize;
	int32_t data[8 * MAX_N + 5];

	void Update(int32_t node, int32_t low, int32_t high, int32_t qInd, int32_t qVal) {
		if(low > qInd || high < qInd) {
			return;
		}
		else if(low == qInd && high == qInd) {
			data[node] = qVal;
			return;
		}

		int32_t mid = (low + high) / 2;
		Update(2 * node, low, mid, qInd, qVal);
		Update(2 * node + 1, mid + 1, high, qInd, qVal);

		if(isMax) {
			data[node] = std::max(data[2 * node], data[2 * node + 1]);
		}
		else {
			data[node] = std::min(data[2 * node], data[2 * node + 1]);
		}
	}

	int32_t Query(int32_t node, int32_t low, int32_t high, int32_t qLow, int32_t qHigh) {
		if(low > qHigh || high < qLow) {
			if(isMax) {
				return -1;
			}
			else {
				return INF;
			}
		}
		else if(low >= qLow && high <= qHigh) {
			return data[node];
		}

		int32_t mid = (low + high) / 2;
		
		if(isMax) {
			return std::max(Query(2 * node, low, mid, qLow, qHigh), Query(2 * node + 1, mid + 1, high, qLow, qHigh));
		}
		else {
			return std::min(Query(2 * node, low, mid, qLow, qHigh), Query(2 * node + 1, mid + 1, high, qLow, qHigh));
		}
	}

public:
	void Init(int32_t _treeSize, bool _isMax) {
		treeSize = _treeSize;
		isMax = _isMax;
	}

	void Update(int32_t ind, int32_t val) {
		Update(1, 1, treeSize, ind, val);
	}

	int32_t Query(int32_t low, int32_t high) {
		return Query(1, 1, treeSize, low, high);
	}
};

int32_t comps[MAX_N + 5], indOf[2 * MAX_N + 5];
std::pair< int32_t, int32_t > a[MAX_N + 5];
SegmentTree segTreeStarts, segTreeEnds;

void Dfs(int32_t ind, int32_t currComp) {
	comps[ind] = currComp;

	segTreeStarts.Update(a[ind].first, -1);
	segTreeEnds.Update(a[ind].second, INF);
	
	while(1) {
		int32_t aux = segTreeStarts.Query(a[ind].first + 1, a[ind].second - 1);
		
		if(aux > a[ind].second) {
			Dfs(indOf[aux], (currComp ^ 1));
		}
		else {
			break;
		}
	}

	while(1) {
		int32_t aux = segTreeEnds.Query(a[ind].first + 1, a[ind].second - 1);
	
		if(aux < a[ind].first) {
			Dfs(indOf[aux], (currComp ^ 1));
		}
		else {
			break;
		}
	}
}

bool Check(int32_t n) {
	std::vector< int32_t > side1, side2;
	for(int32_t i = 0; i < n; i++) {
		if(comps[i] == 0) {
			side1.push_back(i);
		}
		else {
			side2.push_back(i);
		}
	}

	std::stack< int32_t > st;
	for(auto &x : side1) {
		while(!st.empty() && st.top() < a[x].first) {
			st.pop();
		}

		if(!st.empty() && st.top() < a[x].second) {
			return false;
		}
		else {
			st.push(a[x].second);
		}
	}

	while(!st.empty()) {
		st.pop();
	}

	for(auto &x : side2) {
		while(!st.empty() && st.top() < a[x].first) {
			st.pop();
		}

		if(!st.empty() && st.top() < a[x].second) {
			return false;
		}
		else {
			st.push(a[x].second);
		}
	}	

	return true;
}

int main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(nullptr);

	int32_t n;
	std::cin >> n;

	segTreeStarts.Init(2 * n, 1);
	segTreeEnds.Init(2 * n, 0);

	for(int32_t i = 0; i < n; i++) {
		std::cin >> a[i].first >> a[i].second;
	
		segTreeStarts.Update(a[i].first, a[i].second);
		segTreeStarts.Update(a[i].second, -1);

		segTreeEnds.Update(a[i].second, a[i].first);
		segTreeEnds.Update(a[i].first, INF);
	}

	std::sort(a, a + n);
	for(int32_t i = 0; i < n; i++) {
		indOf[a[i].first] = i;
		indOf[a[i].second] = i;
	}

	int32_t cntComps = 0;
	memset(comps, -1, sizeof(comps));
	for(int32_t i = 0; i < n; i++) {
		if(comps[i] == -1) {
			cntComps++;
			Dfs(i, 0);
		}
	}

	if(Check(n)) {
		int32_t ans = 1;
		for(int32_t i = 0; i < cntComps; i++) {
			ans = ((int64_t) 2 * ans) % MOD;
		}

		std::cout << ans << '\n';
	}
	else {
		std::cout << 0 << '\n';
	}
}

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...