제출 #1221973

#제출 시각아이디문제언어결과실행 시간메모리
1221973wiwiho게임 (APIO22_game)C++17
0 / 100
0 ms412 KiB
#include "game.h"

#include <bits/stdc++.h>
using namespace std;

#define StarBurstStream ios_base::sync_with_stdio(false); cin.tie(0);
#define iter(a) a.begin(), a.end()
#define pb emplace_back
#define ff first
#define ss second
#define SZ(a) int(a.size())

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
#ifdef zisk
void debug(){cerr << "\n";}
template<class T, class ... U> void debug(T a, U ... b){cerr << a << " ", debug(b...);}
template<class T> void pary(T l, T r) {
	while (l != r) cerr << *l << " ", l++;
	cerr << "\n";
}
#else
#define debug(...) void()
#define pary(...) void()
#endif

template<typename A, typename B>
ostream& operator<<(ostream& o, pair<A, B> p){
    return o << '(' << p.ff << ',' << p.ss << ')';
}

#define lc 2 * id
#define rc 2 * id + 1
namespace {

    int n, k;
    vector<pii> seg;
    vector<int> pos;
    vector<vector<int>> g, rev;
    vector<int> vst;

    int query(int ql, int qr, int L = -1, int R = k, int id = 1) {
        int M = L + (R - L) / 2;
        if (L == R) return id;
        if (ql <= M && M < qr) return id;
        if (qr <= M) return query(ql, qr, L, M, lc);
        else return query(ql, qr, M + 1, R, rc);
    }
    void push_node(int v, int l, int r) {
        int id = pos[v];
        l = max(l, seg[id].ff);
        r = min(r, seg[id].ss);
        pos[v] = query(l, r, seg[id].ff, seg[id].ss, id);
    }

    int get_come(int v) {
        int id = pos[v];
        if (seg[id].ff == seg[id].ss) return id;
        return lc;
    }
    int get_go(int v) {
        int id = pos[v];
        if (seg[id].ff == seg[id].ss) return id;
        return rc;
    }
    bool isAnc(int a, int b) {
        return seg[a].ff <= seg[b].ff && seg[b].ss <= seg[a].ss;
    }

    void add_edge(int u, int v) {
        g[u].pb(v);
        rev[v].pb(u);
    }

}

void init(int _n, int _k) {
    n = _n;
    k = _k;

    seg.resize(4 * (k + 2));
    pos.resize(n);
    g.resize(n); rev.resize(n);
    vst.resize(n);
    for (int i = 0; i < k - 1; i++)
        add_edge(i, i + 1);
    auto build = [&](auto dfs, int l, int r, int id) -> void {
        debug("build", l, r, id);
        seg[id] = pii(l, r);
        if (l == r) return;
        int m = l + (r - l) / 2;
        dfs(dfs, l, m, lc);
        dfs(dfs, m + 1, r, rc);
    };
    build(build, -1, k, 1);
    debug("ok");
    for (int i = 0; i < n; i++) {
        if (i < k) pos[i] = query(i, i);
        else pos[i] = 1;
    }
    debug("init done");

}

int add_teleporter(int u, int v) {
    debug("test", u, v);
    add_edge(u, v);

    int come = u, go = v;
    bool flag = false;

    auto comp_come = [&](int x, int y) {
        x = get_come(x); y = get_come(y);
        if (x == y) return false;
        if (isAnc(x, y)) return false;
        if (isAnc(y, x)) return true;
        return !(seg[x].ss < seg[y].ff);
    };
    auto comp_go = [&](int x, int y) {
        x = get_go(x); y = get_go(y);
        if (x == y) return false;
        if (isAnc(x, y)) return false;
        if (isAnc(y, x)) return true;
        return !(seg[y].ss < seg[x].ff);
    };

    priority_queue<int, vector<int>, decltype(comp_come)> come_pq(comp_come);
    priority_queue<int, vector<int>, decltype(comp_go)> go_pq(comp_go);

    auto relax_come = [&](int p) {
        debug("relax_come", p);
        if (seg[get_come(p)].ss < seg[get_come(come)].ff) return;
        if (seg[get_come(p)].ss < seg[get_go(go)].ff) return;
        if (seg[get_go(go)].ss <= seg[get_come(p)].ff) {
            flag = true;
            return;
        }
        if (comp_come(come, p)) come = p;
        come_pq.push(p);
    };
    auto relax_go = [&](int p) {
        debug("relax_go", p);
        if (seg[get_go(go)].ss < seg[get_go(p)].ff) return;
        if (seg[get_come(come)].ss < seg[get_go(p)].ff) return;
        if (seg[get_go(p)].ss <= seg[get_come(come)].ff) {
            flag = true;
            return;
        }
        if (comp_go(go, p)) go = p;
        go_pq.push(p);
    };

    relax_come(u);
    relax_go(v);

    vector<int> todo_come;
    vector<int> todo_go;
    debug("ok");

    while (!flag) {
        debug("gao", come, seg[pos[come]], go, seg[pos[go]]);
        if (seg[get_come(come)].ss < seg[get_go(go)].ff) break;
        if (seg[get_go(go)].ss <= seg[get_come(come)].ff)
            return 1;

        assert(isAnc(get_come(come), get_go(go)) || 
                isAnc(get_go(go), get_come(come)));

        if (isAnc(get_come(come), get_go(go))) {
            debug("come");
            assert(!come_pq.empty());
            int now = come_pq.top();
            come_pq.pop();
            if (seg[get_come(now)].ss < seg[get_come(come)].ff) continue;
            push_node(now, -1, seg[get_go(go)].ss);
            todo_come.pb(now);
            for (int i : rev[now])
                relax_come(i);
        }
        else {
            debug("go");
            assert(!go_pq.empty());
            int now = go_pq.top();
            go_pq.pop();
            if (seg[get_go(go)].ss < seg[get_go(now)].ff) continue;
            push_node(now, seg[get_come(come)].ff, k);
            todo_go.pb(now);
            for (int i : g[now])
                relax_go(i);
        }
    }
    
    reverse(iter(todo_come));
    reverse(iter(todo_go));

    for (int now : todo_come) {
        push_node(now, -1, seg[get_go(go)].ss);
        for (int i : g[now])
            push_node(i, seg[get_come(now)].ff, k);
    }
    for (int now : todo_go) {
        push_node(now, seg[get_come(come)].ff, k);
        for (int i : rev[now])
            push_node(i, -1, seg[get_go(now)].ss);
    }
    
    if (flag) return 1;
    if (seg[get_come(come)].ss < seg[get_go(go)].ff) return 0;
    if (seg[get_go(go)].ss <= seg[get_come(come)].ff) return 1;
    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...
#Verdict Execution timeMemoryGrader output
Fetching results...