Submission #1333797

#TimeUsernameProblemLanguageResultExecution timeMemory
1333797nguyengiabach1201Min-max tree (BOI18_minmaxtree)C++20
7 / 100
1096 ms14820 KiB
#include <bits/stdc++.h>
using namespace std;

const int N = 70005;
const int INF = 2e9;

vector<int> adj[N];
int parent[N], depth[N], heavy[N], head[N], pos[N], cur_pos;
int n, k;

// Edge constraints
int min_val[N], max_val[N]; 

struct Query {
    char t;
    int u, v, z;
} queries[N];

// --- HLD Part ---
int dfs_sz(int u) {
    int size = 1, max_c_size = 0;
    for (int v : adj[u]) {
        if (v != parent[u]) {
            parent[v] = u;
            depth[v] = depth[u] + 1;
            int c_size = dfs_sz(v);
            size += c_size;
            if (c_size > max_c_size) {
                max_c_size = c_size;
                heavy[u] = v;
            }
        }
    }
    return size;
}

void dfs_hld(int u, int h) {
    head[u] = h;
    pos[u] = ++cur_pos;
    if (heavy[u]) dfs_hld(heavy[u], h);
    for (int v : adj[u]) {
        if (v != parent[u] && v != heavy[u]) dfs_hld(v, v);
    }
}

// --- Segment Tree for Path Updates ---
int treeMin[4 * N], treeMax[4 * N];

void update(int* tree, int node, int start, int end, int l, int r, int val, bool isMax) {
    if (start > end || start > r || end < l) return;
    if (start >= l && end <= r) {
        if (isMax) tree[node] = max(tree[node], val);
        else tree[node] = min(tree[node], val);
        return;
    }
    int mid = (start + end) / 2;
    update(tree, 2 * node, start, mid, l, r, val, isMax);
    update(tree, 2 * node + 1, mid + 1, end, l, r, val, isMax);
}

int query_point(int* tree, int node, int start, int end, int p, bool isMax) {
    if (start == end) return tree[node];
    int mid = (start + end) / 2;
    int res = tree[node];
    if (p <= mid) {
        int left = query_point(tree, 2 * node, start, mid, p, isMax);
        return isMax ? max(res, left) : min(res, left);
    } else {
        int right = query_point(tree, 2 * node + 1, mid + 1, end, p, isMax);
        return isMax ? max(res, right) : min(res, right);
    }
}

void update_path(int u, int v, int z, bool isMax) {
    int* tree = isMax ? treeMin : treeMax; // treeMin stores 'm' (lower bounds), treeMax stores 'M' (upper bounds)
    while (head[u] != head[v]) {
        if (depth[head[u]] < depth[head[v]]) swap(u, v);
        update(tree, 1, 1, n, pos[head[u]], pos[u], z, isMax);
        u = parent[head[u]];
    }
    if (u == v) return;
    if (depth[u] > depth[v]) swap(u, v);
    update(tree, 1, 1, n, pos[u] + 1, pos[v], z, isMax);
}

// --- Matching Part ---
vector<int> g[N];
int matchL[N], matchR[N], vis[N], timer;

bool dfs_match(int u) {
    vis[u] = timer;
    for (int v : g[u]) {
        if (!matchR[v] || (vis[matchR[v]] != timer && dfs_match(matchR[v]))) {
            matchR[v] = u;
            matchL[u] = v;
            return true;
        }
    }
    return false;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    cin >> n;
    for (int i = 0; i < n - 1; i++) {
        int u, v; cin >> u >> v;
        adj[u].push_back(v); adj[v].push_back(u);
    }

    dfs_sz(1);
    dfs_hld(1, 1);

    for (int i = 0; i < 4 * N; i++) {
        treeMin[i] = -1; 
        treeMax[i] = INF;
    }

    cin >> k;
    for (int i = 1; i <= k; i++) {
        cin >> queries[i].t >> queries[i].u >> queries[i].v >> queries[i].z;
        update_path(queries[i].u, queries[i].v, queries[i].z, queries[i].t == 'm');
    }

    for (int i = 2; i <= n; i++) {
        min_val[i] = query_point(treeMin, 1, 1, n, pos[i], true);
        max_val[i] = query_point(treeMax, 1, 1, n, pos[i], false);
    }

    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= 2; j++) { // Just a placeholder for bipartite construction
            // Logic: if query i's value z matches an edge's min or max constraint
        }
    }
    
    // Simplified bipartite builder:
    for (int i = 2; i <= n; i++) {
        // Link edge i to the constraint query that matches its final min/max
        for(int j=1; j<=k; j++) {
            if((queries[j].t == 'm' && queries[j].z == min_val[i]) || 
               (queries[j].t == 'M' && queries[j].z == max_val[i])) {
                g[j].push_back(i);
            }
        }
    }

    for (int i = 1; i <= k; i++) {
        timer++;
        dfs_match(i);
    }

    for (int i = 2; i <= n; i++) {
        int final_v = matchR[i] ? queries[matchR[i]].z : max(0, min_val[i]);
        if (final_v == -1) final_v = 0; // Default if no constraint
        cout << i << " " << parent[i] << " " << final_v << "\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...