Submission #698868

#TimeUsernameProblemLanguageResultExecution timeMemory
698868_martynasCat in a tree (BOI17_catinatree)C++11
100 / 100
676 ms73796 KiB
#include <bits/stdc++.h>

using namespace std;

using pii = pair<int, int>;
using vi = vector<int>;

#define F first
#define S second
#define PB push_back
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()

const int MXN = 2e5+5;

int n, D;
int P[MXN];
vi adj[MXN];
int depth[MXN];
// centroid
int id = 0;
int level[MXN], par[MXN], where[MXN], sz[MXN];
int dist[25][MXN];
vector<vector<pii>> components;
bool visited[MXN];

void dfs(int u, int p) {
    sz[u] = 1;
    for(int v : adj[u]) if(v != p && !level[v]) {
        dfs(v, u);
        sz[u] += sz[v];
    }
}

int centroid(int u, int p, int tree_sz) {
    for(int v : adj[u]) if(v != p && !level[v]) {
        if(2*sz[v] > tree_sz) {
            return centroid(v, u, tree_sz);
        }
    }
    return u;
}

void set_dist(int u, int p, int lvl, int d) {
    dist[lvl][u] = d;
    for(int v : adj[u]) if(v != p && !level[v]) {
        set_dist(v, u, lvl, d+1);
    }
}

void get_comp(int u, int p, vi &comp) {
    comp.PB(u);
    for(int v : adj[u]) if(v != p && !level[v]) {
        get_comp(v, u, comp);
    }
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    cin >> n >> D;
    for(int i = 1; i < n; i++) {
        cin >> P[i];
        adj[P[i]].PB(i);
        adj[i].PB(P[i]);
    }
    fill(par, par+n, -1);
    int lvl = 1;
    while(id < n) {
        if(id == 0) {
            dfs(0, -1);
            int c = centroid(0, -1, n);
            level[c] = lvl;
            set_dist(c, -1, lvl, 0);
            vi comp; get_comp(c, -1, comp);
            assert(comp.size() == n);
            for(int u : comp) if(u != c) par[u] = c;
            vector<pii> comp_with_dist;
            for(int u : comp) comp_with_dist.PB({dist[lvl][u], u});
            sort(rall(comp_with_dist));
            components.PB(comp_with_dist);
            where[c] = id++;
        }
        else {
            for(int u = 0; u < n; u++) if(level[u] == lvl-1) {
                for(int v : adj[u]) if(!level[v]) {
                    dfs(v, -1);
                    int c = centroid(v, -1, sz[v]);
                    level[c] = lvl;
                    set_dist(c, -1, lvl, 0);
                    vi comp; get_comp(c, -1, comp);
                    for(int i : comp) if(i != c) par[i] = c;
                    vector<pii> comp_with_dist;
                    for(int i : comp) comp_with_dist.PB({dist[lvl][i], i});
                    sort(rall(comp_with_dist));
                    components.PB(comp_with_dist);
                    where[c] = id++;
                }
            }
        }
        lvl++;
    }
//    for(int i = 0; i < id; i++) {
//        cerr << i << ":\n";
//        cerr << "vertices:\n";
//        for(auto p : components[i]) cerr << p.S << " ";
//        cerr << "\n";
//        cerr << "distance from " << components[i].back().S << ":\n";
//        for(auto p : components[i]) cerr << p.F << " ";
//        cerr << "\n";
//    }
    vi order;
    // decreasing distance order from full tree centroid
    for(auto p : components[0]) {
        order.PB(p.S);
    }
    int ans = 0;
    for(int i : order) {
        if(visited[i]) continue;
        visited[i] = true;
        ans++;
        int j = i;
        while(j != -1) {
            int c = where[j];
            while(!components[c].empty() && components[c].back().F + dist[level[j]][i] < D) {
                visited[components[c].back().S] = true;
                components[c].pop_back();
            }
            j = par[j];
        }
    }
    cout << ans << "\n";
    return 0;
}

/*
6 4
0
1
2
2
4

*/

Compilation message (stderr)

In file included from /usr/include/c++/10/cassert:44,
                 from /usr/include/x86_64-linux-gnu/c++/10/bits/stdc++.h:33,
                 from catinatree.cpp:1:
catinatree.cpp: In function 'int main()':
catinatree.cpp:75:32: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
   75 |             assert(comp.size() == n);
      |                    ~~~~~~~~~~~~^~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...