제출 #635293

#제출 시각아이디문제언어결과실행 시간메모리
635293GusterGoose27Port Facility (JOI17_port_facility)C++11
100 / 100
1914 ms615112 KiB
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1e6;
const int inf = 1e9;
const int MOD = 1e9+7;
int n;
int atl[2*MAXN];
int atr[2*MAXN];
vector<int> deact;

class mintree {
public:
	int mn = inf;
	mintree *l = nullptr;
	mintree *r = nullptr;
	int lp, rp;
	mintree(int lv, int rv, int arr[]) {
		lp = lv;
		rp = rv;
		if (lp == rp) {
			if (arr[lp] != -1) mn = arr[lp];
		}
		else {
			int m = (lp+rp)/2;
			l = new mintree(lp, m, arr);
			r = new mintree(m+1, rp, arr);
			mn = min(l->mn, r->mn);
		}
	}
	int query(int lv, int rv) {
		if (lp > rv || rp < lv) return inf;
		if (lp >= lv && rp <= rv) return mn;
		return min(l->query(lv, rv), r->query(lv, rv));
	}
	void upd(int p, int v) {
		if (lp > p || rp < p) return;
		if (lp == rp) {
			if (v == -1) mn = inf;
			else mn = v;
			return;
		}
		l->upd(p, v);
		r->upd(p, v);
		mn = min(l->mn, r->mn);
	}
	int l_contain(int l_lim, int l_req) {
		if (rp < l_lim || mn >= l_req) return inf;
		if (lp == rp) return lp;
		int ans = l->l_contain(l_lim, l_req);
		if (ans < inf) return ans;
		return r->l_contain(l_lim, l_req);
	}
};

class maxtree {
public:
	int mx = -1;
	maxtree *l = nullptr;
	maxtree *r = nullptr;
	int lp, rp;
	maxtree(int lv, int rv, int arr[]) {
		lp = lv;
		rp = rv;
		if (lp == rp) {
			mx = arr[lp];
		}
		else {
			int m = (lp+rp)/2;
			l = new maxtree(lp, m, arr);
			r = new maxtree(m+1, rp, arr);
			mx = max(l->mx, r->mx);
		}
	}
	int query(int lv, int rv) {
		if (lp > rv || rp < lv) return -1;
		if (lp >= lv && rp <= rv) return mx;
		return max(l->query(lv, rv), r->query(lv, rv));
	}
	void upd(int p, int v) {
		if (lp > p || rp < p) return;
		if (lp == rp) {
			mx = v;
			return;
		}
		l->upd(p, v);
		r->upd(p, v);
		mx = max(l->mx, r->mx);
	}
};

mintree *close_contain; // min left
maxtree *far_inter; // max right
mintree *close_inter; // min left
int uf[MAXN];
int sz[MAXN];
bool flip[MAXN];
int id[2*MAXN];

int find(int i) {
	if (uf[i] == -1) return i;
	int np = find(uf[i]);
	flip[i] ^= flip[uf[i]];
	return uf[i] = np;
}

void merge(int a, int b, bool f) {
	int ia = find(a);
	int ib = find(b);
	if (ia == ib) {
		if ((flip[a]^flip[b]) != f) {
			cout << '0' << endl;
			exit(0);
		}
		return;
	}
	uf[ib] = ia;
	sz[ia] += sz[ib];
	flip[ib] = flip[a]^flip[b]^f;
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	cin >> n;
	fill(atl, atl+2*n, -1);
	fill(atr, atr+2*n, -1);
	fill(uf, uf+n, -1);
	fill(sz, sz+n, 1);
	for (int i = 0; i < n; i++) {
		int l, r; cin >> l >> r; l--; r--;
		atr[l] = r;
		atl[r] = l;
		id[l] = id[r] = i;
	}
	close_contain = new mintree(0, 2*n-1, atl);
	far_inter = new maxtree(0, 2*n-1, atr);
	close_inter = new mintree(0, 2*n-1, atl);
	for (int i = 0; i < 2*n; i++) {
		if (atr[i] == -1) continue;
		int r_cont = close_contain->l_contain(atr[i]+1, i);
		assert(r_cont > atr[i]);
		if (r_cont < inf) {
			int mx_r = far_inter->query(i, atr[i]);
			if (mx_r > r_cont) merge(id[i], id[r_cont], 0);
		}
		int lp = close_inter->query(atr[i]+1, r_cont-1);
		while (lp <= atr[i]) {
			deact.push_back(lp);
			merge(id[i], id[lp], 1);
			close_inter->upd(atr[lp], -1);
			lp = close_inter->query(atr[i]+1, r_cont-1);
		}
		for (int v: deact) close_inter->upd(atr[v], v);
		deact.clear();
	}
	int ans = 1;
	for (int i = 0; i < n; i++) {
		if (uf[i] == -1) {
			ans *= 2;
			ans %= MOD;
		}
	}
	cout << ans << "\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...