Submission #1300327

#TimeUsernameProblemLanguageResultExecution timeMemory
1300327eyadoozMin-max tree (BOI18_minmaxtree)C++20
0 / 100
70 ms24984 KiB
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 200005;
vector<pair<int,int>> adj[MAXN];
int n, q;

int parent[20][MAXN], depth[MAXN];
int parEdge[MAXN];
int edgeValue[MAXN];
int upEdge[20][MAXN];

void dfs(int u, int p, int pedge, int d){
    parent[0][u] = p;
    depth[u] = d;
    parEdge[u] = pedge;
    for(auto &e: adj[u]){
        int v=e.first, id=e.second;
        if(v==p) continue;
        dfs(v, u, id, d+1);
    }
}

int lca(int a,int b){
    if(depth[a] < depth[b]) swap(a,b);
    int diff = depth[a] - depth[b];
    for(int i=0;i<20;i++)
        if(diff & (1<<i)) a = parent[i][a];
    if(a==b) return a;
    for(int i=19;i>=0;i--)
        if(parent[i][a] != parent[i][b]){
            a = parent[i][a];
            b = parent[i][b];
        }
    return parent[0][a];
}

void assign_on_path(int u, int anc, int val, bool isMin){
    // isMin = true => all edges >= val
    // isMin = false => all edges <= val
    while(u != anc){
        int id = parEdge[u];
        if(isMin) edgeValue[id] = max(edgeValue[id], val);
        else edgeValue[id] = min(edgeValue[id], val);
        u = parent[0][u];
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    for(int i=0;i<n-1;i++){
        int u,v;
        cin >> u >> v;
        adj[u].push_back({v,i});
        adj[v].push_back({u,i});
        edgeValue[i] = 0;       // initial = 0
    }

    dfs(1,0,-1,0);

    for(int i=1;i<20;i++)
        for(int u=1;u<=n;u++)
            parent[i][u] = parent[i-1][ parent[i-1][u] ];

    cin >> q;
    struct Q { bool isMin; int u,v,z; };
    vector<Q> queries;

    while(q--){
        char c;
        int u,v,z;
        cin >> c >> u >> v >> z;
        queries.push_back({c=='m', u, v, z});
    }

    // sort queries by z increasing
    sort(queries.begin(), queries.end(), [](auto &a, auto &b){
        return a.z < b.z;
    });

    // Apply constraints
    for(auto &qr : queries){
        int u=qr.u, v=qr.v, z=qr.z;
        int w = lca(u,v);

        if(qr.isMin){
            // path must have all edges >= z
            assign_on_path(u, w, z, true);
            assign_on_path(v, w, z, true);
        } else {
            // path must have all edges <= z
            if(edgeValue[ parEdge[w] ]); // ignore
            assign_on_path(u, w, z, false);
            assign_on_path(v, w, z, false);
        }
    }

    // Second pass: ensure at least one edge equals z for each query
    for(auto &qr: queries){
        int u=qr.u, v=qr.v, z=qr.z;
        int w=lca(u,v);

        bool placed=false;

        // Try path u -> w
        int x=u;
        while(x!=w){
            int id=parEdge[x];
            if(edgeValue[id]==z){ placed=true; break; }
            x = parent[0][x];
        }

        // Try path v -> w
        x=v;
        while(!placed && x!=w){
            int id=parEdge[x];
            if(edgeValue[id]==z){ placed=true; break; }
            x = parent[0][x];
        }

        if(!placed){
            // assign the first edge on the u→w path
            x=u;
            if(x!=w){
                int id = parEdge[x];
                edgeValue[id] = z;
                continue;
            }
            // otherwise assign first edge on v→w
            x=v;
            int id = parEdge[x];
            edgeValue[id] = z;
        }
    }

    // Output
    for(int u=1;u<=n;u++){
        for(auto &e: adj[u]){
            int v=e.first, id=e.second;
            if(u < v){
                cout << u << " " << v << " " << edgeValue[id] << "\n";
            }
        }
    }
    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...