题解:P14383 [JOISC 2017] 港口设施 / Port Facility
先转化题目条件,显然当
考虑给每个区间按右端点排序,排完序后就是找
所以可以把找到的区间合并成一个大区间,每个区间加入一次合并一次,复杂度是
找区间和合并这些区间可以使用线段树,插入区间
最后跑一遍二分图染色,答案为
#include <bits/stdc++.h>
#define fi first
#define se second
#define int long long
using namespace std;
using pii = pair<int, int>;
const int kMaxN = 2e6 + 5, mod = 1e9 + 7;
int n, L, R, ans = 1, col[kMaxN];
pii a[kMaxN];
vector<int> e[kMaxN];
struct SegTree {
int t[kMaxN << 3];
void query(int x, int l, int r, int a) {
if (l > a || t[x] < a) return;
if (l == r) {
L = min(L, l), R = max(R, t[x]);
e[a].push_back(l), e[l].push_back(a);
t[x] = -0x3f3f3f3f;
return;
}
int m = l + r >> 1;
query(x << 1, l, m, a), query(x << 1 | 1, m + 1, r, a);
t[x] = max(t[x << 1], t[x << 1 | 1]);
}
void update(int x, int l, int r, int a, int v) {
if (l > a || r < a) return;
if (l == r) {
t[x] = v;
return;
}
int m = l + r >> 1;
update(x << 1, l, m, a, v), update(x << 1 | 1, m + 1, r, a, v);
t[x] = max(t[x << 1], t[x << 1 | 1]);
}
} tr;
void dfs(int x) {
for (int i : e[x])
if (!col[i]) col[i] = 3 - col[x], dfs(i);
else if (col[i] == col[x]) ans = 0;
}
signed main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i].fi >> a[i].se;
sort(a + 1, a + n + 1, [](pii a, pii b){ return a.se < b.se; });
memset(tr.t, -0x3f, sizeof(tr.t));
for (int i = 1; i <= n; i++) {
L = 1e9, R = 0, tr.query(1, 1, 2 * n, a[i].fi);
if (L <= R) tr.update(1, 1, 2 * n, L, R);
tr.update(1, 1, 2 * n, a[i].fi, a[i].se);
}
for (int i = 1; i <= n; i++)
if (!col[a[i].fi])
col[a[i].fi] = 1, dfs(a[i].fi), ans = ans * 2 % mod;
cout << ans;
return 0;
}