이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using namespace std;
#define f1r(i, a, b) for (int i = a; i < b; i++)
#define f0r(i, a) f1r(i, 0, a)
#define trav(t, a) for (auto& t : a)
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define f first
#define s second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
typedef vector<int> vi;
typedef long long ll;
typedef pair<int, int> pi;
typedef vector<pi> vpi;
template <class T> struct SparseTable {
    std::vector<T> v;
    std::vector<std::vector<int>> jump;
    int level(int x) {
        return 31 - __builtin_clz(x);
    }
    int comb(int a, int b) {
        return v[a] == v[b] ? std::min(a, b) : (v[a] < v[b] ? a : b);
    }
    void init(const std::vector<T>& _v) {
        v = _v;
        jump = {std::vector<int>((int) v.size())};
        iota(jump[0].begin(), jump[0].end(), 0);
        for (int j = 1; (1 << j) <= (int) v.size(); j++) {
            jump.push_back(std::vector<int>((int) v.size() - (1 << j) + 1));
            for (int i = 0; i < (int) jump[j].size(); i++) {
                jump[j][i] = comb(jump[j - 1][i], jump[j - 1][i + (1 << (j - 1))]);
            }
        }
    }
    int index(int l, int r) {
        assert(l <= r);
        int d = level(r - l + 1);
        return comb(jump[d][l], jump[d][r - (1 << d) + 1]);
    }
    T query(int l, int r) {
        return v[index(l, r)];
    }
};
struct LCAJump {
    int n;
    std::vector<std::vector<int>> par;
    std::vector<std::vector<int>> adj;
    std::vector<int> depth;
    void init(int _n) {
        n = _n;
        int d = 1;
        while ((1 << d) < n) d++;
        par.assign(d, std::vector<int>(n));
        adj.resize(n);
        depth.resize(n);
    }
    void ae(int x, int y) {
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    void gen(int root = 0) {
        par[0][root] = root;
        dfs(root);
    }
    void dfs(int src = 0) {
        for (int i = 1; i < (int) par.size(); i++) {
            par[i][src] = par[i - 1][par[i - 1][src]];
        }
        for (int nxt: adj[src]) {
            if (nxt == par[0][src]) continue;
            depth[nxt] = depth[par[0][nxt] = src] + 1;
            dfs(nxt);
        }
    }
    int jump(int x, int d) {
        for (int i = 0; i < (int) par.size(); i++) {
            if ((d >> i) & 1) {
                x = par[i][x];
            }
        }
        return x;
    }
    
    int lca(int x, int y) {
        if (depth[x] < depth[y]) std::swap(x, y);
        x = jump(x, depth[x] - depth[y]);
        if (x == y) return x;
        for (int i = (int) par.size() - 1; i >= 0; i--) {
            int nx = par[i][x];
            int ny = par[i][y];
            if (nx != ny) x = nx, y = ny;
        }
        return par[0][x];
    }
};
template <class T> struct LazySeg {
    std::vector<T> sum, lazy;
    int sz;
    void init(int sz_) {
        sz = 1;
        while (sz < sz_) sz *= 2;
        sum.assign(2 * sz, 0);
        lazy.assign(2 * sz, 0);
    }
    void push(int ind, int L, int R) {
        sum[ind] += (R - L + 1) * lazy[ind];
        if (L != R) {
            lazy[2 * ind] += lazy[ind];
            lazy[2 * ind + 1] += lazy[ind];
        }
        lazy[ind] = 0;
    }
    void pull(int ind) {
        sum[ind] = sum[2 * ind] + sum[2 * ind + 1];
    }
    void build() {
        for (int i = sz - 1; i >= 1; i--) {
            pull(i);
        }
    }
    void upd(int lo, int hi, T inc, int ind = 1, int L = 0, int R = -1) {
        if (R == -1) R += sz;
        push(ind, L, R);
        if (hi < L || R < lo) return ;
        if (lo <= L && R <= hi) {
            lazy[ind] = inc;
            push(ind, L, R);
            return;
        }
        int M = (L + R) / 2;
        upd(lo, hi, inc, 2 * ind, L, M);
        upd(lo, hi, inc, 2 * ind + 1, M + 1, R);
        pull(ind);
    }
    T qsum(int lo, int hi, int ind = 1, int L = 0, int R = -1) {
        if (R == -1) R += sz;
        push(ind, L, R);
        if (lo > R || L > hi) return 0;
        if (lo <= L && R <= hi) return sum[ind];
        int M = (L + R) / 2;
        return qsum(lo, hi, 2 * ind, L, M) + qsum(lo, hi, 2 * ind + 1, M + 1, R);
    }
};
const bool VALUES_IN_VERTICES = false;
template <class T> class HeavyLight {
    std::vector<int> parent, heavy, depth, root, tree_pos;
    LazySeg<T> tree;
    template <class G> int dfs(const G& graph, int v) {
        int size = 1, max_subtree = 0;
        for (int u : graph[v]) if (u != parent[v]) {
            parent[u] = v;
            depth[u] = depth[v] + 1;
            int subtree = dfs(graph, u);
            if (subtree > max_subtree) heavy[v] = u, max_subtree = subtree;
            size += subtree;
        }
        return size;
    }
    template <class B> void process_path(int u, int v, B op) {
        for (; root[u] != root[v]; v = parent[root[v]]) {
            if (depth[root[u]] > depth[root[v]]) std::swap(u, v);
            op(tree_pos[root[v]], tree_pos[v]);
        }
        if (depth[u] > depth[v]) std::swap(u, v);
        op(tree_pos[u] + (VALUES_IN_VERTICES ? 0 : 1), tree_pos[v]);
    }
public:
    template <class G>
    void init(const G& graph, vi& roots) {
        int n = (int) graph.size();
        heavy.assign(n, -1);
        parent.assign(n, 0);
        depth.assign(n, 0);
        root.assign(n, 0);
        tree_pos.assign(n, 0);
        tree.init(n);
        trav(r, roots) {
            parent[r] = -1;
            depth[r] = 0;
            dfs(graph, r);
        }
        for (int i = 0, current_pos = 0; i < n; ++i)
            if (parent[i] == -1 || heavy[parent[i]] != i)
            for (int j = i; j != -1; j = heavy[j]) {
                root[j] = i;
                tree_pos[j] = current_pos++;
            }
    }
    void modify_path(int u, int v, const T& value) {
        process_path(u, v, [this, &value](int l, int r) { tree.upd(l, r, value); });
    }
    
    T query_path(int u, int v) {
        T res = 0;
        process_path(u, v, [this, &res](int l, int r) { res += tree.qsum(l, r); });
        return res;
    }
};
struct BCC {
    int n, time, num_comps; 
    std::vector<int> ord, low, id; 
    // order encountered, earliest time in subtree, component id
    std::vector<std::vector<int>> adj, comps, tree;
    // adj, comps storage, bridge block tree
    std::vector<std::pair<int, int>> bridge;
    // bridges
    
    void init(int n_) {
        num_comps = time = 0;
        n = n_;
        ord.assign(n, -1);
        low.assign(n, 0);
        id.assign(n, -1);
        adj.assign(n, std::vector<int>());
        comps.clear();
        tree.clear();
    }
    void ae(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    bool is_bridge(int u, int v) {
        if (ord[u] > ord[v])
            std::swap(u, v);
        return ord[u] < low[v];
    }
    void dfs(int src, int par) {
        ord[src] = low[src] = time++;
        bool bic = false; // accounts for double edges
        for (int nxt : adj[src]) { 
            if (nxt == par && !bic) {
                bic = true;
                continue;
            }
            if (ord[nxt] != -1) {
                low[src] = std::min(low[src], ord[nxt]);
                continue;
            }
            dfs(nxt, src);
            low[src] = std::min(low[src], low[nxt]);
            if (is_bridge(src, nxt))
                bridge.emplace_back(src, nxt);
        }
    }
    void fill_component(int src) {
        comps[id[src]].push_back(src);
        for (int nxt : adj[src]) {
            if (id[nxt] != -1 || is_bridge(nxt, src))
                continue;
            id[nxt] = id[src];
            fill_component(nxt);
        }
    }
    void add_component(int src) {
        if (id[src] != -1)
            return;
        id[src] = num_comps++;
        comps.emplace_back();
        fill_component(src);
    }
    
    int build() {
        for (int i = 0; i < n; i++) 
            if (ord[i] == -1)
                dfs(i, -1);
        for (int i = 0; i < n; i++) 
            add_component(i);
        tree.resize(num_comps);
        for (auto& b : bridge) {
            int u = id[b.first];
            int v = id[b.second];
            tree[u].push_back(v);
            tree[v].push_back(u);            
        }
        return num_comps;
    }
};
int n, m, sz;
HeavyLight<int> H;
BCC B;
LCAJump L;
map<pi, int> conv;
pi cp(int u, int v) {
    if (u > v) swap(u, v);
    return {u, v};
}
int main() {
    cin.tie(0)->sync_with_stdio(0);
    int n, m; cin >> n >> m;
    B.init(n);
    vi ans(m, -1); // -1 is both
    vector<array<int, 3>> ed;
    f0r(i, m) {
        int u, v; cin >> u >> v;
        u--, v--;
        B.ae(u, v);
        ed.pb({u, v, i});
    }
    B.build();
    trav(e, ed) {
        if (B.id[e[0]] != B.id[e[1]]) {
            int u = B.id[e[0]];
            int v = B.id[e[1]];
            conv[mp(u, v)] = e[2];
        }
    }
    vpi tree;
    vi vis(sz(B.tree));
    function<void(int, int)> dfs = [&](int src, int par) {
        if (par != -1) {
            tree.eb(src, par);
        }
        vis[src] = 1;
        trav(nxt, B.tree[src]) {
            if (nxt == par) continue;
            dfs(nxt, src);
        }
    };
    vi roots;
    f0r(i, sz(B.tree)) 
        if (!vis[i]) 
            dfs(i, -1), roots.pb(i);
    H.init(B.tree, roots);
    L.init(sz(B.tree));
    trav(e, tree) {
        L.ae(e.f, e.s);
    }
    trav(r, roots) L.gen(r);
    int p; cin >> p;
    f0r(i, p) {
        int x, y; cin >> x >> y;
        // all things from x to y are directed  
        x--, y--;
        int u = B.id[x];
        int v = B.id[y];
        if (u != v) {
            int lca = L.lca(u, v);
            assert(lca < sz(B.tree));
            H.modify_path(u, lca, 1);
            H.modify_path(v, lca, -1);
        }
    }
    trav(e, tree) {
        int u = e.f;
        int p = e.s;
        int val = H.query_path(u, p);
        int l = -1;
        int r = -1;
        if (val > 0) {
            l = u;
            r = p;
        } else if (val < 0) {
            l = p;
            r = u;
        }
        if (l != -1) {
            if (conv.find({l, r}) != conv.end()) {
                ans[conv[{l, r}]] = 1;
            } else {
                ans[conv[{r, l}]] = 0;
            }
        }
    }
    f0r(i, m) {
        if (ans[i] == -1) {
            cout << "B";
        } else if (ans[i] == 1) {
            cout << "R";
        } else {
            cout << "L";
        }
    }
    cout << '\n';
    return 0;
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |