제출 #1343574

#제출 시각아이디문제언어결과실행 시간메모리
1343574biankMin-max tree (BOI18_minmaxtree)C++20
100 / 100
177 ms30728 KiB
#include <bits/stdc++.h>
 
using namespace std;
 
#define forsn(i, s, n) for (int i = int(s); i < int(n); i++)
#define forn(i, n) forsn(i, 0, n)
#define dforsn(i, s, n) for (int i = int(n) - 1; i >= int(s); i--)
#define dforn(i, n) dforsn(i, 0, n)
 
using vi = vector<int>;
using ii = pair<int, int>;
using vii = vector<ii>;
using ll = long long;
using ld = long double;
using vll = vector<ll>;
using vb = vector<bool>;
using pll = pair<ll, ll>;

#define sz(x) int(x.size())
#define all(x) begin(x), end(x)

#define pb push_back
#define eb emplace_back

#define fst first
#define snd second

const int MAX_N = 70'005;
const int MAX_LOG = 17;

vi adj[MAX_N];
int up[MAX_LOG][MAX_N], depth[MAX_N];
int mini[MAX_LOG][MAX_N], maxi[MAX_LOG][MAX_N];

void dfs(int u, int p = 0) {
    up[0][u] = p, depth[u] = depth[p] + 1;
    forn(i, MAX_LOG - 1) up[i + 1][u] = up[i][up[i][u]];
    for (int v : adj[u]) if (v != p) dfs(v, u);
}

vi g[MAX_N];
int match[MAX_N];
bitset<MAX_N> vis;

bool solve(int u) {
    if (u == -1) return true;
    if (vis[u]) return false;
    vis[u] = true;
    for (int v : g[u]) if (solve(match[v])) {
        match[v] = u;
        return true;
    }
    return false;
}

int main() {
    ios::sync_with_stdio(0);         
    cin.tie(0); cout.tie(0);
    
    int n;
    cin >> n;
    forn(i, n - 1) {
        int x, y;
        cin >> x >> y;
        adj[x].pb(y);
        adj[y].pb(x);
    }
    
    depth[0] = -1;
    dfs(1);
    
    forn(i, MAX_LOG) forn(u, n + 1) {
        mini[i][u] = 0;
        maxi[i][u] = 1'000'000'001;
    }
    
    int q;
    cin >> q;
    map<int, int> id;
    vi value;
    forn(k, q) {
        char type;
        int x, y, z;
        cin >> type >> x >> y >> z;
        id[z] = k;
        value.pb(z);
        if (depth[x] < depth[y]) swap(x, y);
        if (type == 'm') {
            dforn(i, MAX_LOG) if (depth[x] - (1 << i) >= depth[y]) {
                mini[i][x] = max(mini[i][x], z);
                x = up[i][x]; 
            }
            dforn(i, MAX_LOG) if (up[i][x] != up[i][y]) {
                mini[i][x] = max(mini[i][x], z);
                mini[i][y] = max(mini[i][y], z);
                x = up[i][x], y = up[i][y];
            }
            if (x != y) {
                mini[0][x] = max(mini[0][x], z);
                mini[0][y] = max(mini[0][y], z);
            }
        } else {
            dforn(i, MAX_LOG) if (depth[x] - (1 << i) >= depth[y]) {
                maxi[i][x] = min(maxi[i][x], z);
                x = up[i][x]; 
            }
            dforn(i, MAX_LOG) if (up[i][x] != up[i][y]) {
                maxi[i][x] = min(maxi[i][x], z);
                maxi[i][y] = min(maxi[i][y], z);
                x = up[i][x], y = up[i][y];
            }
            if (x != y) {
                maxi[0][x] = min(maxi[0][x], z);
                maxi[0][y] = min(maxi[0][y], z);
            }
        }
    }
    
    dforn(i, MAX_LOG - 1) forn(u, n + 1) {
        int v = up[i][u];
        maxi[i][u] = min(maxi[i][u], maxi[i + 1][u]);
        maxi[i][v] = min(maxi[i][v], maxi[i + 1][u]);
        mini[i][u] = max(mini[i][u], mini[i + 1][u]);
        mini[i][v] = max(mini[i][v], mini[i + 1][u]);
    }
    
    forn(u, n + 1) match[u] = -1;
    
    forsn(u, 2, n + 1) {
        int l = mini[0][u], r = maxi[0][u];
        if (id.count(l)) g[u].pb(id[l]);
        if (id.count(r)) g[u].pb(id[r]);
    }
    
    forn(u, n + 1) {
        vis.reset();
        solve(u);
    }
    
    vi w(n + 1);
    forsn(u, 2, n + 1) w[u] = maxi[0][u];
    
    forn(i, q) if (match[i] != -1) {
        w[match[i]] = value[i];
    }
    
    forsn(u, 2, n + 1) {
        cout << u << " " << up[0][u] << " " << w[u] << "\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...