Submission #1248372

#TimeUsernameProblemLanguageResultExecution timeMemory
1248372dfhdfhdsfPapričice (COCI20_papricice)C++20
15 / 110
14 ms24132 KiB
#include <bits/stdc++.h>
using namespace std;

static const int MAXN = 200000;
int n;
vector<int> g[MAXN+1];
int parentArr[MAXN+1], sz[MAXN+1];
int tin[MAXN+1], tout[MAXN+1], dfsTime = 0;
int orderByTin[MAXN+1];

// 1) DFS flatten & tính subtree size
void dfs(int u, int p){
    parentArr[u] = p;
    tin[u] = ++dfsTime;
    orderByTin[dfsTime] = u;
    sz[u] = 1;
    for(int v: g[u]){
        if(v == p) continue;
        dfs(v, u);
        sz[u] += sz[v];
    }
    tout[u] = dfsTime;
}

// 2) Segment tree lưu vector<int> đã sort
vector<int> seg[4*MAXN+4];

void build(int idx, int l, int r){
    if(l == r){
        int v = orderByTin[l];
        seg[idx] = { sz[v] };
    } else {
        int mid = (l+r)>>1;
        build(idx<<1, l, mid);
        build(idx<<1|1, mid+1, r);
        auto &L = seg[idx<<1], &R = seg[idx<<1|1];
        seg[idx].resize(L.size() + R.size());
        merge(L.begin(), L.end(), R.begin(), R.end(), seg[idx].begin());
    }
}

// Trả về pair{best ≤ target, best ≥ target}, minus là -INF nếu không có, plus là +INF nếu không có.
pair<int,int> query(int idx, int l, int r, int ql, int qr, int target){
    if(ql > r || qr < l) return { -1, n+1 };
    if(ql <= l && r <= qr){
        // binary search trong seg[idx]
        auto &V = seg[idx];
        auto it_hi = lower_bound(V.begin(), V.end(), target);
        int hi = (it_hi==V.end() ? n+1 : *it_hi);
        int lo = -1;
        if(it_hi != V.begin()){
            lo = *prev(it_hi);
        }
        return { lo, hi };
    }
    int mid = (l+r)>>1;
    auto L = query(idx<<1, l, mid, ql, qr, target);
    auto R = query(idx<<1|1, mid+1, r, ql, qr, target);
    // gộp kết quả
    int lo = max(L.first, R.first);
    int hi = min(L.second, R.second);
    return { lo, hi };
}

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

    cin >> n;
    for(int i = 1,u,v; i < n; i++){
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    // Chọn root = 1
    dfsTime = 0;
    dfs(1,0);

    build(1,1,n);

    int answer = n; // ban đầu đặt lớn
    // Duyệt mọi đỉnh != root (ứng với cắt cạnh (u, parent[u]))
    for(int u = 2; u <= n; u++){
        int T = sz[u];
        int X = n - T;

        // 1) cắt lần 2 trong thành phần subtree u: đoạn [tin[u], tout[u]]
        {
            int target = T/2;
            auto pr = query(1,1,n, tin[u], tout[u], target);
            for(int s: {pr.first, pr.second}){
                if(s <= 0 || s >= T) continue;
                int a = s, b = T - s, c = X;
                int mx = max({a,b,c}), mn = min({a,b,c});
                answer = min(answer, mx - mn);
            }
        }

        // 2) cắt lần 2 trong thành phần ngoài subtree u: 
        //    hai đoạn [1, tin[u]-1] và [tout[u]+1, n]
        {
            int target = X/2;
            // [1, tin[u]-1]
            if(tin[u] > 1){
                auto pr = query(1,1,n, 1, tin[u]-1, target);
                for(int s: {pr.first, pr.second}){
                    if(s <= 0 || s >= X) continue;
                    int a = s, b = X - s, c = T;
                    int mx = max({a,b,c}), mn = min({a,b,c});
                    answer = min(answer, mx - mn);
                }
            }
            // [tout[u]+1, n]
            if(tout[u] < n){
                auto pr = query(1,1,n, tout[u]+1, n, target);
                for(int s: {pr.first, pr.second}){
                    if(s <= 0 || s >= X) continue;
                    int a = s, b = X - s, c = T;
                    int mx = max({a,b,c}), mn = min({a,b,c});
                    answer = min(answer, mx - mn);
                }
            }
        }
    }

    cout << answer << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...