Submission #45582

#TimeUsernameProblemLanguageResultExecution timeMemory
45582kuzmichev_dimaPort Facility (JOI17_port_facility)C++14
100 / 100
5715 ms153696 KiB
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cassert>
#include <cmath>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <cstdlib>
#include <unordered_set>

using namespace std;

#define INF 1e+9
#define mp make_pair
#define pb push_back
#define fi first
#define fs first
#define se second
#define i64 long long
#define li long long
#define lint long long
#define pii pair<int, int>
#define vi vector<int>

#define forn(i, n) for (int i = 0; i < (int)n; i++)
#define fore(i, b, e) for (int i = (int)b; i <= (int)e; i++)

#define MAX_FLAG 0
#define MIN_FLAG 1

const int MOD = 1e9+7;
const int maxn = 1e6+5;
const int inf = 1e9;

typedef int Tree[maxn * 8];

int s[maxn];
int f[maxn];
int inits[maxn];
int initf[maxn];
int n;
unordered_set<int> in_process;
Tree tree_max, tree_min;
int s_pos_to_i[2 * maxn];
int f_pos_to_i[2 * maxn];
int color[maxn];
int undef;

inline int select_max(int fi, int se) {
    return f[fi] > f[se] ? fi : se;
}

inline int select_min(int fi, int se) {
    return s[fi] < s[se] ? fi : se;
}

int get(const Tree& tree, int i, int L, int R, int A, int B, bool flag) {
    //printf("get i = %d L = %d R = %d A = %d B = %d\n", i, L, R, A, B);
    if (L >= B || A >= R)
        return undef;
    if (L >= A && R <= B)
        return tree[i];
    int M = (L + R) / 2;
    int g1 = get(tree, 2 * i, L, M, A, B, flag);
    int g2 = get(tree, 2 * i + 1, M, R, A, B, flag);
    return flag == MAX_FLAG ? select_max(g1, g2) : select_min(g1, g2);
}

void upd(Tree& tree, int i, int L, int R, int pos, bool flag) {
    if (L + 1 == R) {
        tree[i] = undef;
        return;
    }
    int M = (L + R) / 2;
    if (pos < M)
        upd(tree,i * 2, L, M, pos, flag);
    else upd(tree, i * 2 + 1, M, R, pos, flag);
    tree[i] = (flag == MIN_FLAG ? select_min(tree[i * 2], tree[i * 2 + 1]) : select_max(tree[i * 2], tree[i * 2 + 1]));
}

inline void add(int num) {
    in_process.insert(num);
    upd(tree_max, 1, 0, 2 * n, s[num], MAX_FLAG);
    upd(tree_min, 1, 0, 2 * n, f[num], MIN_FLAG);
    f[num] = -inf;
    s[num] = inf;
}

void build(Tree& tree, int i, int L, int R, bool flag) {
    // printf("build i = %d L = %d R = %d\n", i, L, R);
    if (L + 1 == R) {
        tree[i] = flag == MIN_FLAG ? f_pos_to_i[L] : s_pos_to_i[L];
        return;
    }
    int M = (L + R) / 2;
    build(tree, 2 * i, L, M, flag);
    build(tree, 2 * i + 1, M, R, flag);
    tree[i] = (flag == MIN_FLAG ? select_min(tree[i * 2], tree[i * 2 + 1]) : select_max(tree[i * 2], tree[i * 2 + 1]));
}

struct Event {
    int num, x, typ;
};

bool operator < (Event first, Event second) {
    return first.x < second.x;
}

int main() {
#ifdef LOCAL
    freopen("inp", "r", stdin);
    //freopen("outp", "w", stdout);
#else
    // freopen(TASKNAME ".in", "r", stdin);
    // freopen(TASKNAME ".out", "w", stdout);
#endif
    scanf("%d", &n);
    undef = n;
    s[undef] = inf;
    f[undef] = -inf;
    forn(i, n) {
        scanf("%d%d", &s[i], &f[i]);
        --s[i];
        --f[i];
        inits[i] = s[i];
        initf[i] = f[i];
        //printf("s[%d] =%d f[%d] = %d\n", i, s[i], i, f[i]);
    }
    forn(i, 2 * n) {
        f_pos_to_i[i] = s_pos_to_i[i] = undef;
    }
    forn(i, n) {
        f_pos_to_i[f[i]] = i;
        s_pos_to_i[s[i]] = i;
    }
    forn(i, n)
        color[i] = 2;
    build(tree_min, 1, 0, 2 * n, MIN_FLAG);
    build(tree_max, 1, 0, 2 * n, MAX_FLAG);
    int ans = 1;
    /*forn(i, n) {
        printf("s[%d] = %d f[%d] = %d\n", i, s[i], i, f[i]);
    }*/
    int start = 0;
    while(true) {
        while(start < n && color[start] != 2)
            ++start;
        if (start == n)
            break;
        //printf("\n================\n");
        //printf("start = %d\n", start);
        ans = ans * 2 % MOD;
        color[start] = 0;
        add(start);
        while(!in_process.empty()) {
            int x = *in_process.begin();
            //printf("x = %d [%d; %d]\n", x, inits[x], initf[x]);
            in_process.erase(in_process.begin());
            while(true) {
                int next = get(tree_max, 1, 0, 2 * n, inits[x] + 1, initf[x], MAX_FLAG);
                //printf("next = %d\n", next);
                if (next == undef || f[next] < initf[x])
                    break;
                color[next] = 1 - color[x];
                add(next);
            }
            while(true) {
                int next = get(tree_min, 1, 0, 2 * n, inits[x] + 1, initf[x], MIN_FLAG);
                if (next == undef || s[next] > inits[x])
                    break;
                color[next] = 1 - color[x];
                add(next);
            }
        }
    }
    vector<Event> events;
    forn(i, n) {
        events.pb({i, inits[i], 1});
        events.pb({i, initf[i], -1});
    }
    sort(events.begin(), events.end());
    set<int> S[2];
/*    forn(i, n)
        printf("color[%d] = %d\n", i, color[i]);*/
    for (const Event& event : events) {
        //printf("event x = %d num = %d typ = %d\n", event.x, event.num, event.typ);
        if (event.typ == 1) {
            if (!S[color[event.num]].empty()) {
                //printf("begin = %d\n", *S[1 - color[event.num]].begin());
                if (*S[color[event.num]].begin() < initf[event.num]) {
                    printf("0");
                    exit(0);
                }
            }
            S[color[event.num]].insert(initf[event.num]);
        } else {
            S[color[event.num]].erase(initf[event.num]);
        }
    }
    printf("%d\n", ans);
}

Compilation message (stderr)

port_facility.cpp: In function 'int main()':
port_facility.cpp:121:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d", &n);
     ~~~~~^~~~~~~~~~
port_facility.cpp:126:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d%d", &s[i], &f[i]);
         ~~~~~^~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...