Submission #370096

#TimeUsernameProblemLanguageResultExecution timeMemory
370096fishy15Port Facility (JOI17_port_facility)C++14
78 / 100
6014 ms85492 KiB
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <array>
#include <algorithm>
#include <utility>
#include <map>
#include <queue>
#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <numeric>

#define ll long long
#define ld long double
#define eps 1e-8
#define MOD 1000000007

#define INF 0x3f3f3f3f
#define NINF 0xc0c0c0c0
#define INFLL 0x3f3f3f3f3f3f3f3f

// change if necessary
#define MAXN 1000010

using namespace std;

int n;
pair<int, int> pts[MAXN];
int l_inv[MAXN];
int r_inv[MAXN];
int vis[MAXN]; // 0 unvis, 1 in first stack, 2 in second stack

struct segtree {
    int st[8 * MAXN];
    segtree() { memset(st, NINF, sizeof st); }
    void upd(int x, int y, int v = 1, int l = 0, int r = 2 * n) {
        if (l == r) {
            st[v] = y;
        } else {
            int m = (l + r) / 2;
            if (x <= m) {
                upd(x, y, 2 * v, l, m);
            } else {
                upd(x, y, 2 * v + 1, m + 1, r);
            }
            st[v] = max(st[2 * v], st[2 * v + 1]);
        }
    }
    int qry(int x, int y, int v = 1, int l = 0, int r = 2 * n) {
        if (r < x || l > y) {
            return NINF;
        } else if (x <= l && r <= y) {
            return st[v];
        } else {
            int m = (l + r) / 2;
            return max(qry(x, y, 2 * v, l, m), qry(x, y, 2 * v + 1, m + 1, r));
        }
    }
};

ll modpow(ll x, ll e) {
    ll res = 1;
    while (e) {
        if (e & 1) res = res * x % MOD;
        x = x * x % MOD;
        e >>= 1;
    }
    return res;
}

// left_end is min left end whose right is within a given range
// right_end is max right end whose left is within a given range
segtree left_end, right_end;

void dfs(int x, int c) {
    left_end.upd(pts[x].second, NINF);
    right_end.upd(pts[x].first, NINF);
    vis[x] = c;

    int q;
    while ((q = -left_end.qry(pts[x].first, pts[x].second)) < pts[x].first) {
        int left_loc = l_inv[q];
        dfs(left_loc, 3 - c);
    }

    while ((q = right_end.qry(pts[x].first, pts[x].second)) > pts[x].second) {
        int right_loc = r_inv[q];
        dfs(right_loc, 3 - c);
    }
}

int sz_a, sz_b;
int a[2 * MAXN];
int b[2 * MAXN];
int cur_stack[MAXN];
int r = 0;
bool check(int *tot, int sz) {
    sort(tot, tot + sz);

    for (int i = 0; i < sz; i++) {
        int x = tot[i];
        if (l_inv[x] != -1) {
            cur_stack[r++] = l_inv[x];
        } else {
            if (r == 0 || cur_stack[r - 1] != r_inv[x]) {
                return false;
            }
            r--;
        }
    }
    
    return true;
}

int main() {
    cin.tie(0)->sync_with_stdio(0);

    cin >> n;

    memset(l_inv, -1, sizeof l_inv);
    memset(r_inv, -1, sizeof r_inv);
    for (int i = 0; i < n; i++) {
        int a, b; cin >> a >> b;
        pts[i] = {a, b};
        l_inv[a] = i;
        r_inv[b] = i;
    }

    for (int i = 0; i < n; i++) {
        left_end.upd(pts[i].second, -pts[i].first);
        right_end.upd(pts[i].first, pts[i].second);
    }

    int cnt = 0;
    for (int i = 0; i < n; i++) {
        if (!vis[i]) {
            cnt++;
            dfs(i, 1);
        }
    }
    
    for (int i = 0; i < n; i++) {
        if (vis[i] == 1) {
            a[sz_a++] = pts[i].first;
            a[sz_a++] = pts[i].second;
        } else {
            b[sz_b++] = pts[i].first;
            b[sz_b++] = pts[i].second;
        }
    }

    if (check(a, sz_a) && check(b, sz_b)) {
        cout << modpow(2, cnt) << '\n';
    } else {
        cout << "0\n";
    }

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...