Submission #1357722

#TimeUsernameProblemLanguageResultExecution timeMemory
1357722yyc000123Team Coding (EGOI24_teamcoding)C++20
23 / 100
4091 ms48628 KiB
#include<bits/stdc++.h>
using namespace std ;
#define F first
#define S second
const int N = 1e5+5 ;
int n , m , k , color[N] , par[N] , deep[N] , in[N] , out[N] , t ;
vector<int> child[N] , cpos[N] , dcnt[N] , cd[N] ;
pair<int,int> ans ;

void dfs(int node){
    in[node]=++t ;
    dcnt[deep[node]].push_back(in[node]) ;
    cd[color[node]].push_back(deep[node]) ;
    for(int i:child[node]) deep[i]=deep[node]+1 , dfs(i) ;
    out[node]=++t ;
}

void dfs1(int node , int c){
    if(color[node]==c){
        vector<int> v , v1 ;
        queue<pair<int,int>> q ;
        q.push({node,0}) ;
        int temp = 0 , change = 0 ;
        while(!q.empty()){
            int x = q.front().F , d = q.front().S ; q.pop() ;
            if(v.size()<=d) v.push_back(0) , v1.push_back(0) ;
            if(color[x]==color[node]) temp++ , v1[d]++ ;
            else v[d]++ ;
            for(int i:child[x]) q.push({i,d+1}) ;
        }
        for(int i=0 ; i<v.size() ; i++){
            int cur = upper_bound(cd[color[node]].begin(),cd[color[node]].end(),deep[node]+i)-lower_bound(cd[color[node]].begin(),cd[color[node]].end(),deep[node]+i) ;
            temp+=min(v[i],cur-v1[i]) ; change+=min(v[i],cur-v1[i]) ;
        }
        ans = max(ans,{temp,-change}) ;
        return ;
    }
    for(int i:child[node]) dfs1(i,c) ;
}

int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) ;
    cin >> n >> k ; par[0] = -1 ; m = sqrt(n) ;
    for(int i=0 ; i<n ; i++) cin >> color[i] , cpos[color[i]].push_back(i) ;
    for(int i=1 ; i<n ; i++) cin >> par[i] , child[par[i]].push_back(i) ;
    dfs(0) ;
    for(int i=0 ; i<k ; i++){
        sort(cd[i].begin(),cd[i].end()) ;
        if(cd[i].size()<=m){
            dfs1(0,i) ; continue ;
        }
        for(int j:cpos[i]){
            map<int,int> mp1 , mp2 , mp3 ; // deep , not in subtree same color/subtree sum/subtree same color
            for(int l:cpos[i]){
                if(deep[l]<=deep[j]) continue ;
                // is l belongs to j's subtree (if in[j]<in[l] then is)
                // search in[j] <= dcnt[deep[l]][...] <= out[j] is the size of deep = l in subtree j
                // dcnt[deep[l]] is the size of deep = l in all tree
                int cur1 = upper_bound(dcnt[deep[l]].begin(),dcnt[deep[l]].end(),out[j])-dcnt[deep[l]].begin() ;
                int cur2 = lower_bound(dcnt[deep[l]].begin(),dcnt[deep[l]].end(),in[j])-dcnt[deep[l]].begin() ;
                mp2[deep[l]]=cur1-cur2 ;
                if(in[j]<in[l] && out[l]<out[j]) mp3[deep[l]]++ ;
                else mp1[deep[l]]++ ;
            }
            pair<int,int> temp = {1,0} ;
            for(auto it:mp2){
                temp.F+=mp3[it.F]+min(mp2[it.F]-mp3[it.F],mp1[it.F]) ;
                temp.S+=min(mp2[it.F]-mp3[it.F],mp1[it.F]) ;
            }
            temp.S*=-1 ;
            ans=max(ans,temp) ;
        }
    }
    cout << ans.F << ' ' << -ans.S << '\n' ;
    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...
#Verdict Execution timeMemoryGrader output
Fetching results...