Submission #1243586

#TimeUsernameProblemLanguageResultExecution timeMemory
1243586Sam_arvandiCapital City (JOI20_capital_city)C++20
100 / 100
465 ms165832 KiB
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define FOR(i, j, n) for (int i = j; i<= n; i++)
#define ROF(i, n, j) for (int i = n; i>= j; i--)
#define pb push_back
#define mp make_pair
#define S second
#define F first
#define IOS ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0)

/*
#pragma GCC optimization("Ofast, unroll-loops")
#pragma GCC target("avx2")
#pragma GCC target("bmi")
#pragma GCC target("bmi2")
#pragma GCC target("lzcnt")
*/

const int mn = 2e5 + 5, mlg = 22, mn2 = 6e5 + 10;
vector<int> A[mn2], a[mn], A2[mn2];
vector<pii> a2[mn];
int h[mn], siz[mn], par[mn], nemd[mn], beg[mn], c[mn], lift[mn][mlg];
int root[mn], g[mn], Siz[mn];
int k[mn], num[mn2];
bool mark[mn], MARK[mn2], MARK2[mn2], flag[mn2];
vector<int> melat[mn2];
struct Seg_tree
{
        struct Node
        {
                int lc = -1, rc = -1;
        }tmp;
        int n = 0;
        vector<Node> node;

        void init(int id, int L, int R)
        {
                if (L+1 == R)
                {
                        A[id].pb(nemd[L]);
                        return;
                }
                n++;
                node.pb(tmp);
                node[id].lc = n;
                A[id].pb(n);
                n++;
                node.pb(tmp);
                node[id].rc = n;
                A[id].pb(n);
                int mid = (L+R)/2;
                init(node[id].lc, L, mid);
                init(node[id].rc, mid, R);
        }


        void add(int id, int L, int R, int l, int r, int u)
        {
                if (L == l and R == r)
                {
                        A[u].pb(id);
                        return;
                }
                int mid = (L+R)/2;
                if (l >= mid) add(node[id].rc, mid, R,l, r, u);
                else if (r <= mid) add(node[id].lc, L, mid, l, r, u);
                else
                {
                        add(node[id].lc, L, mid, l, mid, u);
                        add(node[id].rc, mid, R, mid, r, u);
                }
        }
}seg;

void dfs(int u)
{
        mark[u] =1;
        siz[u] =1;
        for(auto v: a[u])
        {
                if (mark[v])
                {
                        par[u] = v;
                        lift[u][0] = v;
                        continue;
                }
                h[v] = h[u]+1;
                dfs(v);
                siz[u] += siz[v];
                a2[u].pb(mp(siz[v], v));
        }
}

void dfs2(int u)
{
        int v;
        for(auto p: a2[u])
        {
                v = p.S;
                if (v == a2[u][0].S)
                {
                        root[v] = root[u];
                }
                else root[v] = v;
                dfs2(v);
        }
}

vector<int> alaki;
void DFS(int u)
{
        MARK[u] = 1;
        for(auto v: A[u])
        {
                if (!MARK[v]) DFS(v);
        }
        alaki.pb(u);
}

int ind = 0;
void DFS2(int u)
{
        num[u] = ind;
        melat[ind].pb(u);
        MARK2[u] = 1;
        for(auto v: A2[u])
        {
                if (!MARK2[v]) DFS2(v);
        }
        return;
}
struct HLD
{
        void init(int n)
        {
                FOR(i, 1, n)
                {
                        if (a2[i].size() != 0) continue;
                        Siz[root[i]] = 0;
                        int u = i;
                        while (root[u] != u)
                        {
                                Siz[root[u]]++;
                                g[u] = Siz[root[u]];
                                nemd[Siz[root[u]]] = c[u];
                                u = par[u];
                        }
                        Siz[root[u]]++;
                        g[u] = Siz[root[u]];
                        nemd[Siz[root[u]]] = c[u];
                        seg.n++;
                        beg[u] = seg.n;
                        seg.node.pb(seg.tmp);
                        seg.init(seg.n, 1, Siz[u]+1);
                }
        }

        void update(int u, int v, int x)
        {
                if (h[root[u]] <= h[v])
                {
                        seg.add(beg[root[u]], 1, Siz[root[u]]+1, g[u], g[v]+1, x);
                }
                else
                {
                        seg.add(beg[root[u]], 1, Siz[root[u]]+1, g[u], Siz[root[u]]+1, x);
                        update(par[root[u]], v, x);
                }
                return;
        }
}hld;

int get_lca(int u, int v)
{
        if (h[u] < h[v]) swap(u, v);
        ROF(i, 20, 0)
        {
                if (h[lift[u][i]] >= h[v])
                {
                        u = lift[u][i];
                }
        }
        if (u == v) return u;
        ROF(i, 20, 0)
        {
                if (lift[u][i] != lift[v][i])
                {
                        u = lift[u][i];
                        v = lift[v][i];
                }
        }
        return par[u];
}


signed main()
{
        IOS;
        int n, m, u, v;
        cin >> n >> m;
        FOR(i,1 , n-1)
        {
                cin >> u >> v;
                a[u].pb(v);
                a[v].pb(u);
        }
        FOR(i, 1, n)
        {
                cin >>c[i];
        }
        FOR(i, 0, m)
        {
                seg.n++;
                seg.node.pb(seg.tmp);
        }
        h[1] = 1;
        dfs(1);
        FOR(j, 1, 20)
        {
                FOR(i, 1, n)
                {
                        lift[i][j] = lift[lift[i][j-1]][j-1];
                }
        }
        FOR(i,1 , n)
        {
                sort(a2[i].begin(), a2[i].end());
                reverse(a2[i].begin(), a2[i].end());
        }
        root[1] = 1;
        dfs2(1);
        //return 0;
        FOR(i, 1, n)
        {
                if (k[c[i]] == 0) k[c[i]] = i;
                else k[c[i]] = get_lca(i, k[c[i]]);
        }
        
        hld.init(n);
        FOR(i, 1, n)
        {
                hld.update(i, k[c[i]], c[i]);
        }
        //return 0;
        int N = seg.n;

        FOR(i, 1, N)
        {
                for(auto v: A[i])
                {
                        A2[v].pb(i);
                }
        }
        FOR(i, 1, N)
        {
                if (!MARK[i])
                {
                        //cout << i << endl;
                        DFS(i);
                }
        }
        reverse(alaki.begin(), alaki.end());
        for(auto i: alaki)
        {
                if (!MARK2[i])
                {
                        ind++;
                        DFS2(i);
                }
        }
        FOR(i, 1, N)
        {
                for(auto v: A[i])
                {
                        if (num[v] != num[i]) flag[num[i]] = 1;
                }
        }
        int ans = N, ted =0;
        FOR(i, 1, ind)
        {
                if (flag[i]) continue;
                ted = 0;
                for(auto v: melat[i])
                {
                        if (v > m) continue;
                        ted++;
                }
                if (ted != 0) ans = min(ans, ted);
        }
        cout << ans-1;
        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...