제출 #1352430

#제출 시각아이디문제언어결과실행 시간메모리
1352430retardeMeetings 2 (JOI21_meetings2)C++20
100 / 100
289 ms74164 KiB
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define se second
#define int long long
#define all(x) (x).begin(), (x).end()

typedef long double ld;
typedef long long ll;
typedef pair<ll,ll> pll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<bool> vb;
typedef vector<vector<int>> vvi;
typedef vector<vector<bool>> vvb;
typedef vector<vector<ll>> vvll;
typedef vector<string> vs;
typedef vector<vector<string>> vvs;
typedef vector<char> vc;
typedef vector<vector<char>> vvc;
typedef map<int, int> mii;
typedef unordered_map<int, int> umii;

const int mod = 1e9 + 7;
const int inf = INTMAX_MAX;
const bool tc = false;

int n;
const int mxn = 2e5 + 1;
vi adj[mxn]; int depth[mxn], sub[mxn], par[mxn], tin[mxn], tout[mxn], up[mxn][20];

int timer = -1;
void dfs(int node, int prev, int d) {
    depth[node] = d;
    int sb = 1;
    tin[node] = ++timer;
    for (auto &neighbour : adj[node]) {
        if (neighbour == prev) continue;
        dfs(neighbour, node, d+1);
        sb += sub[neighbour];
    }
    sub[node] = sb;
    par[node] = up[node][0] = prev;
    tout[node] = timer;
}

bool anc(int u, int v) {
    return (tin[u] <= tin[v] && tout[v] <= tout[u]);
}

int lca(int u, int v) {
    if (depth[u] < depth[v]) swap(u, v);
    for (int j = 19; j >= 0; j--) {
        if (up[u][j] == -1) continue;
        int p = up[u][j];
        // if (anc(p, v)) continue;
        // u = p;
        if (depth[p] >= depth[v]) u = p;
    }
    // u = up[u][0];
    if (u == v) return v;
    for (int j = 19; j >= 0; j--) {
        int u2 = up[u][j];
        int v2 = up[v][j];
        if (u2 == v2) continue;
        u = u2; v = v2;
    }
    return up[u][0];
}

int dist(int u, int v) { return depth[u] + depth[v] - 2 * depth[lca(u, v)]; }

struct dia {
    int a, b, v;
    bool operator<(const dia &other) const {
        if (v != other.v) return v < other.v;
        else if (a != other.a) return a < other.a;
        else return b < other.b;
    }
};

class DisjointSets {
  private:
	vector<int> parents;
	vector<int> sizes;
    vector<dia> diams;
    int mxd;

  public:
	DisjointSets(int size) : parents(size), sizes(size, 1), diams(size) {
		for (int i = 0; i < size; i++) {
            parents[i] = i;
            diams[i] = {i, i, 0};
        }
        mxd = 0;
	}

	/** @return the "representative" node in x's component */
	int find(int x) { return parents[x] == x ? x : (parents[x] = find(parents[x])); }

	/** @return whether the merge changed connectivity */
	bool unite(int x, int y) {
		int x_root = find(x);
		int y_root = find(y);
		if (x_root == y_root) { return false; }
		if (sizes[x_root] < sizes[y_root]) { swap(x_root, y_root); swap(x, y); }

        vector<dia> cand;
        cand.pb(diams[x_root]); cand.pb(diams[y_root]);
        // farthest from x
        pii p = max(mp(dist(x, diams[x_root].a), diams[x_root].a), mp(dist(x, diams[x_root].b), diams[x_root].b));
        pii q = max(mp(dist(y, diams[y_root].a), diams[y_root].a), mp(dist(y, diams[y_root].b), diams[y_root].b));
        cand.pb({p.se, q.se, p.fi + q.fi + 1}); 
        diams[x_root] = *max_element(all(cand));
        mxd = max(mxd, diams[x_root].v);

		sizes[x_root] += sizes[y_root];
		parents[y_root] = x_root;

		return true;
	}

	/** @return whether x and y are in the same connected component */
	bool connected(int x, int y) { return find(x) == find(y); }

    int diam() { return mxd; }
};

inline void solve() {
    cin >> n;
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        adj[u].pb(v);
        adj[v].pb(u);
    }

    dfs(0, -1, 0);
    for (int j = 1; j < 20; j++) {
        for (int i = 0; i < n; i++) {
            if (up[i][j - 1] == -1) {
                up[i][j] = -1;
                continue;
            }
            up[i][j] = up[up[i][j - 1]][j - 1];
        }
    }
    vector<pair<int, pii>> edge;
    for (int i = 1; i < n; i++) {
        edge.push_back({min(sub[i], n - sub[i]), {i, par[i]}});
    }
    sort(all(edge)); reverse(all(edge));
    DisjointSets dsu(n); vi ans(n+1);

    int ptr = 0;
    for (int s = n/2; s >= 1; s--) {
        // two comp of size s
        while (ptr < edge.size()) {
            if (edge[ptr].fi < s) break;
            dsu.unite(edge[ptr].se.fi, edge[ptr].se.se);
            ptr++;
        }
        ans[s*2] = dsu.diam() + 1;
    }

    for (int i = 1; i <= n; i++) {
        if (i % 2) cout << "1\n";
        else cout << ans[i] << '\n';
    }
}

void setIO(string s) {
    freopen((s + ".in").c_str(), "r", stdin);
    freopen((s + ".out").c_str(), "w", stdout);
}

signed main() {
    ios::sync_with_stdio(false);
    cout.tie(0);
    cin.tie(0);
    //setIO();

    int t = 1;
    if (tc) {
        cin >> t;
    }

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

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

meetings2.cpp: In function 'void setIO(std::string)':
meetings2.cpp:179:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  179 |     freopen((s + ".in").c_str(), "r", stdin);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
meetings2.cpp:180:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  180 |     freopen((s + ".out").c_str(), "w", stdout);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...