Submission #987070

#TimeUsernameProblemLanguageResultExecution timeMemory
987070AverageAmogusEnjoyerOne-Way Streets (CEOI17_oneway)C++17
100 / 100
124 ms41076 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
 
template<class T> bool cmin(T &i,T j) { return i > j ? i = j,true: false; }
template<class T> bool cmax(T &i,T j) { return i < j ? i = j,true: false; }

struct RMQ {
    int n;
    int lg;
    vector<vector<int>> sparse;
    RMQ() {}
    RMQ(vector<int> a) {
        if (a.empty()) { return; }
        n = (int)a.size();
        lg = 0;
        while((1<<lg) <= n) { lg++; }
        sparse.assign(lg,vector<int>(n));
        sparse[0] = a;
        for (int pw=1;pw<lg;pw++) {
            for (int i=0;i<n;i++) {
                sparse[pw][i] = min(sparse[pw-1][i],sparse[pw-1][min(i+(1<<(pw-1)),n-1)]);
            }
        }
    }
    int qry(int l,int r) {
        assert(0 <= l && l <= r && r < n);
        int bit = 31-__builtin_clz(r-l+1);
        return min(sparse[bit][l],sparse[bit][r-(1<<bit)+1]);
    }
};

struct LCA {
    int n;
    vector<vector<pair<int,int>>> adj;
    vector<bool> vst;
    vector<int> tin,where;
    vector<vector<int>> path,ret;
    // modify this to allow query on forest
    vector<RMQ> rmq;
    int timer = 0;
    LCA(int N,vector<vector<pair<int,int>>> a) {
        adj = a;
        n = N;
        tin.resize(n);
        where.resize(n);
        vst.assign(n,false);
        for (int x=0;x<n;x++) if (!vst[x]) {
            timer = 0;
            path.emplace_back();
            ret.emplace_back();
            dfs(x,-1);
            rmq.push_back(RMQ(ret.back()));
        }
    }
    void dfs(int x,int z) {
        tin[x] = timer++;
        assert(!vst[x]);
        vst[x] = true;
        where[x] = (int)path.size() - 1;
        for (auto &[y,idx]: adj[x]) if (y != z) {
            path.back().push_back(x),ret.back().push_back(tin[x]);
            dfs(y,x);
        }
    }
    int lca(int x,int y) { 
        if (x == y) { return x; }
        assert(where[x] == where[y]);
        if (tin[x] > tin[y]) { swap(x,y); }
        return path[where[x]][rmq[where[x]].qry(tin[x],tin[y]-1)];
    }
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    string ans(m,'B');
    vector<vector<pair<int,int>>> adj(n);
    vector<pair<int,int>> edges(m);
    for (int i=0,x,y;i<m;i++) {
        cin >> x >> y;
        --x,--y;
        edges[i] = make_pair(x,y);
        adj[x].emplace_back(y,i);
        adj[y].emplace_back(x,i);
    }
    vector<vector<pair<int,int>>> tree(n);
    // vector<vector<pair<int,int>>> back_edges(n);
    vector<int> dp(n);
    vector<int> t(n,-1);
    int timer = 0;
    vector<bool> vst(n);
    vector<int> par(n);
    auto dfs = [&](auto &self,int x,int z) -> void {
        t[x] = timer++;
        vst[x]=true;
        par[x]=z;
        for (auto &[y,idx]: adj[x]) if (y != z) {
            if (t[y] > t[x]) {
                // back_edges[y].emplace_back(x,idx);
                // cout << "back edge: " << y+1 << " " << x+1 << endl;
                dp[y]++;
                dp[x]--;
            } else if (t[y] == -1) {
                tree[x].emplace_back(y,idx);
                tree[y].emplace_back(x,idx);
                // cout << "span edge: " << x+1 << " " << y+1 << endl;
                self(self,y,x);
            }
        }
    };
    vst.assign(n,false);
    for (int x=0;x<n;x++) if (!vst[x]) { 
        dfs(dfs,x,-1);
    }
    auto dfstree = [&](auto &self,int x,int z) -> void {
        vst[x]=true;
        for (auto &[y,idx]: tree[x]) if (y != z) {
            self(self,y,x);
            dp[x] += dp[y];
        }
    };
    vst.assign(n,false);
    for (int x=0;x<n;x++) if (!vst[x]) { 
        dfstree(dfstree,x,-1);
    }
    vector<int> up(n),down(n);
    LCA tr(n,tree);
    int q;
    cin >> q;
    for (int x,y;q--;) {
        cin >> x >> y;
        --x,--y;
        int l = tr.lca(x,y);
        /*
        vst.assign(n,false);
        int cx = x;
        while(cx != -1) {
            vst[cx] = true;
            cx = par[cx];
        }
        int cy = y;
        while(!vst[cy]) {
            cy = par[cy];
            assert(cy != -1);
        }
        int l = cy;
        */
        up[x]++;
        up[l]--;
        down[y]++;
        down[l]--;
    }
    auto dfspush = [&](auto &self,int x,int z) -> void {
        vst[x]=true;
        for (auto &[y,idx]: tree[x]) if (y != z) {
            self(self,y,x);
            up[x] += up[y];
            down[x] += down[y];
        
            // actually write down edge
            if (dp[y] != 0) { continue; } 
            assert(up[y] == 0 || down[y] == 0);
            if (up[y]) {
                if (edges[idx].second == x) {
                    ans[idx] = 'R';
                } else {
                    ans[idx] = 'L';
                }
            } else if (down[y]) {
                if (edges[idx].second == y) {
                    ans[idx] = 'R';
                } else {
                    ans[idx] = 'L';
                }
            }
        }
    };
    vst.assign(n,false);
    for (int x=0;x<n;x++) if (!vst[x]) { 
        dfspush(dfspush,x,-1); 
    }
    cout << ans << endl;    
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...