제출 #1362634

#제출 시각아이디문제언어결과실행 시간메모리
1362634iamhereforfunPort Facility (JOI17_port_facility)C++20
0 / 100
45 ms63028 KiB
// Starcraft 2 enjoyer //

#include <bits/stdc++.h>

// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")

using namespace std;

#define LSOne(X) ((X) & -(X))

const int N = 2e6 + 5;
const int M = 1e6 + 5;
const int B = 18;
const long long K = 2;
const int LG = 20;
const int INF = 1e9 + 5;
const int P = 31;
const int MOD = 1e9 + 7;
const int nx[] = {0, 1, 0, -1}, ny[] = {-1, 0, 1, 0};

struct SegmentTree
{
    vector<int> mx, mn;
    int n;
    void update(int v, int val, int pos, int l, int r)
    {
        if (l == r)
        {
            mx[v] = val;
            mn[v] = val;
        }
        else
        {
            int m = (l + r) / 2;
            if (pos <= m)
            {
                update(2 * v, val, pos, l, m);
            }
            else
            {
                update(2 * v + 1, val, pos, m + 1, r);
            }
            mn[v] = min(mn[2 * v], mn[2 * v + 1]);
            mx[v] = max(mx[2 * v], mx[2 * v + 1]);
        }
    }
    int getMn(int v, int l, int r, int tl, int tr)
    {
        if (tl > tr)
            return INF;
        if (tl <= l && r <= tr)
        {
            return mn[v];
        }
        else
        {
            int m = (l + r) / 2;
            return min(getMn(2 * v, l, m, tl, min(tr, m)), getMn(2 * v + 1, m + 1, r, max(tl, m + 1), tr));
        }
    }
    int getMx(int v, int l, int r, int tl, int tr)
    {
        if (tl > tr)
            return -1;
        if (tl <= l && r <= tr)
        {
            return mx[v];
        }
        else
        {
            int m = (l + r) / 2;
            return max(getMx(2 * v, l, m, tl, min(tr, m)), getMx(2 * v + 1, m + 1, r, max(tl, m + 1), tr));
        }
    }
    SegmentTree(int len)
    {
        n = len;
        mn.assign(4 * n, INF);
        mx.assign(4 * n, -1);
    }
    void update(int val, int pos)
    {
        update(1, val, pos, 0, n - 1);
    }
    int getMn(int l, int r)
    {
        return getMn(1, 0, n - 1, l, r);
    }
    int getMx(int l, int r)
    {
        return getMx(1, 0, n - 1, l, r);
    }
};

struct Dsu
{
    vector<int> parent, type;
    vector<int> size;
    Dsu(int n)
    {
        parent.assign(n + 1, 0);
        size.assign(n + 1, 1);
        type.assign(n + 1, 0);
        for (int x = 0; x < n + 1; x++)
        {
            parent[x] = x;
        }
    }
    pair<int, int> getParent(int x)
    {
        if (parent[x] == x)
        {
            return {x, 0};
        }
        else
        {
            pair<int, int> p = getParent(parent[x]);
            parent[x] = p.first;
            type[x] ^= p.second;
            return {parent[x], type[x]};
        }
    }
    void update(int a, int b)
    {
        a = getParent(a).first;
        b = getParent(b).first;
        if (a != b)
        {
            if (size[a] < size[b])
            {
                swap(a, b);
            }
            parent[b] = a;
            type[b] ^= 1;
            size[a] += size[b];
        }
    }
    bool compare(int i, int j)
    {
        return getParent(i).second == getParent(j).second;
    }
    bool chkConnect(int i, int j)
    {
        return getParent(i).first == getParent(j).first;
    }
};

int n, nxt[N], lst[N];
pair<int, bool> type[N];
pair<int, int> port[N];
long long ans;

inline void calNxt()
{
    SegmentTree st(N);
    for (int x = 2 * n; x >= 1; x--)
    {
        auto [a, b] = port[type[x].first];
        // cout << a << " " << b << " " << x << "\n";
        if (type[x].second)
        {
            int i = st.getMn(a, b);
            // cout << i << " " << a << "\n";
            if (i == INF)
                nxt[a] = -1;
            else
                nxt[a] = i;
            st.update(a, a);
        }
        else
        {
            st.update(INF, a);
        }
    }
}

inline void calLst()
{
    SegmentTree st(N);
    for (int x = 1; x <= 2 * n; x++)
    {
        auto [a, b] = port[type[x].first];
        // cout << a << " " << b << " " << x << "\n";
        if (!type[x].second)
        {
            int i = st.getMx(a, b);
            if (i == -1)
                lst[a] = -1;
            else
                lst[a] = i;
            st.update(b, b);
        }
        else
        {
            st.update(-1, b);
        }
    }
}

inline void solve()
{
    cin >> n;
    for (int x = 0; x < n; x++)
    {
        int a, b;
        cin >> a >> b;
        type[a] = {x, 0};
        type[b] = {x, 1};
        port[x] = {a, b};
    }
    ans = 1;
    calNxt();
    // cout << "\n";
    calLst();
    Dsu dsu(2 * n);
    for (int x = 1; x <= 2 * n; x++)
    {
        if (type[x].second)
            continue;
        if (lst[x] != -1)
        {
            if (dsu.chkConnect(port[type[lst[x]].first].first, x))
            {
                if (dsu.compare(port[type[lst[x]].first].first, x))
                {
                    cout << 0 << "\n";
                    return;
                }
            }
            dsu.update(port[type[lst[x]].first].first, x);
        }
        if (nxt[x] != -1)
        {
            if (dsu.chkConnect(port[type[nxt[x]].first].first, x))
            {
                if (dsu.compare(port[type[nxt[x]].first].first, x))
                {
                    cout << 0 << "\n";
                    return;
                }
            }
            dsu.update(port[type[nxt[x]].first].first, x);
        }
        if (lst[x] != -1 && nxt[x] != -1)
        {
            if (lst[x] > nxt[x])
            {
                cout << 0 << "\n";
                return;
            }
        }
    }
    // cout << "\n";
    for (int x = 1; x <= 2 * n; x++)
    {
        if (type[x].second)
            continue;
        if (dsu.getParent(x).first == x)
        {
            // cout << x << "\n";
            ans *= 2;
            ans %= MOD;
        }
    }
    cout << ans << "\n";
}

signed main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    for (int x = 1; x <= t; x++)
    {
        solve();
    }
    return 0;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…