제출 #1265609

#제출 시각아이디문제언어결과실행 시간메모리
1265609CodeLakVNPapričice (COCI20_papricice)C++20
0 / 110
21 ms42820 KiB
#include <bits/stdc++.h>
using namespace std;

#define task "main"
#define F first
#define S second
#define ii pair<int, int>
#define il pair<int, long long>
#define li pair<long long, int>
#define FOR(i, a, b) for(int i = (a); i <= (b); ++i)
#define FOD(i, b, a) for(int i = (b); i >= (a); --i)

template <class T1, class T2>
    bool maximize(T1 &a, T2 b){
        if (a < b) {a = b; return true;}
        return false;
    }

template <class T1, class T2>
    bool minimize(T1 &a, T2 b){
        if (a > b) {a = b; return true;}
        return false;
    }

template <class T>
    void printArr(T container, string separator = " ", string finish = "\n", ostream &out = cout){
        for(auto item: container) out << item << separator;
        out << finish;
    }

const int MAX_N = (int)2e5 + 5;
const int INF = (int)1e9 + 1408;

int nNode;
vector<int> adj[MAX_N];

int sz[MAX_N];
int in[MAX_N], out[MAX_N], node[MAX_N];
int timer = 0;

struct IT {
    multiset<int> tree[4 * MAX_N];

    void build(int id, int l, int r) {
        if (l == r) {
            tree[id].insert(sz[node[l]]);
            return;
        }
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
        tree[id] = tree[id << 1];
        for (int x : tree[id << 1 | 1]) tree[id].insert(x);
//        cout << "RANGE " << l << " " << r << "\n";
//        for (int x : tree[id]) cout << x << " ";
//        cout << "\n";
    }

    void update(int pos, int oldVal, int newVal) {
        int id = 1, l = 1, r = nNode;
        while (true) {
            tree[id].erase(tree[id].find(oldVal));
            tree[id].insert(newVal);
            if (l == r) return;
            int mid = (l + r) >> 1;
            if (pos <= mid) {
                id = id << 1;
                r = mid;
            }
            else {
                id = id << 1 | 1;
                l = mid + 1;
            }
        }
    }

    ii get(int id, int l, int r, int u, int v, int val) {
        if (l > v || r < u) return {-1, INF};
        if (l >= u && r <= v) {
            auto it = tree[id].upper_bound(val);
            int larger = (it == tree[id].end() ? INF : (*it));
            int smaller = (it == tree[id].begin() ? -1 : (*(--it)));
            return make_pair(smaller, larger);
        }
        int mid = (l + r) >> 1;
        ii A = get(id << 1, l, mid, u, v, val);
        ii B = get(id << 1 | 1, mid + 1, r, u, v, val);
        return make_pair(max(A.F, B.F), min(A.S, B.S));
    }

    ii get(int l, int r, int val) {
        if (l > r) return make_pair(-1, INF);
        return get(1, 1, nNode, l, r, val);
    }
} magic;

void dfs(int u, int p) {
    in[u] = ++timer;
    node[in[u]] = u;
    sz[u] = 1;
    for (int v : adj[u]) if (v != p)
        dfs(v, u), sz[u] += sz[v];
    out[u] = timer;
}

int ans = INF;

int calc(int x, int y, int z) {
    return max({x, y, z}) - min({x, y, z});
}

void reroot(int u, int p, int oldSize) {
    if (u != 1 && (nNode - oldSize) / 2 >= oldSize) {
        ii a = magic.get(1, in[u] - 1, (nNode - oldSize) / 2);
        ii b = magic.get(out[u] + 1, nNode, (nNode - oldSize) / 2);
//        cout << "NODE " << u << " " << oldSize << ":\n";
//        cout << 1 << " " << in[u] - 1 << ": " << a.F << ", " << a.S << "\n";
//        cout << out[u] + 1 << " " << nNode << ": " << b.F << ", " << b.S << "\n";
        int x = max(a.F, b.F), y = min(a.S, b.S);
        minimize(ans, calc(oldSize, x, nNode - x - oldSize));
        minimize(ans, calc(oldSize, y, nNode - y - oldSize));
//        cout << "ANS: " << ans << "\n";
    }

    for (int v : adj[u]) if (v != p) {
        int oldU = sz[u], oldV = sz[v];
        sz[u] -= sz[v];
        sz[v] = nNode;
        magic.update(in[u], oldU, sz[u]);
        magic.update(in[v], oldV, sz[v]);
        reroot(v, u, oldV);
        magic.update(in[u], sz[u], oldU);
        magic.update(in[v], sz[v], oldV);
        sz[u] = oldU;
        sz[v] = oldV;
    }
}

void solve() {
    cin >> nNode;
    FOR(i, 1, nNode - 1) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    dfs(1, -1);
    magic.build(1, 1, nNode);

    reroot(1, -1, 0);

    cout << ans;
}

int32_t main() {
    if (fopen(task".inp", "r")) {
        freopen(task".inp", "r", stdin);
        freopen(task".out", "w", stdout);
    }
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    bool multitest = 0;
    int numTest = 1;
    if (multitest) cin >> numTest;

    while (numTest--) {
        solve();
    }

    return 0;
}

/* Lak lu theo dieu nhac!!!! */

컴파일 시 표준 에러 (stderr) 메시지

papricice.cpp: In function 'int32_t main()':
papricice.cpp:158:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  158 |         freopen(task".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
papricice.cpp:159:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  159 |         freopen(task".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...