제출 #1331051

#제출 시각아이디문제언어결과실행 시간메모리
1331051JuanJLCat Exercise (JOI23_ho_t4)C++20
100 / 100
673 ms180376 KiB
#include <bits/stdc++.h>

#define fst first
#define snd second
#define pb push_back
#define SZ(x) (int)x.size()
#define ALL(x) x.begin(),x.end()
#define forn(i,a,b) for(int i = a; i<b; i++)
#define mset(a,v) memset(a,v,sizeof(a))
#define FIN ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

using namespace std;
typedef long long ll;

const int MAXN = 200000+5;
const int MAXP = 20;

#ifdef D
    #define debug(x) cout << x
#else
    #define debug(x) //nothing
#endif

ll n;
ll p[MAXN];
ll res[MAXN];
vector<ll> adj[MAXN];

struct UnionFind{
    ll n; 
    vector<ll> rep;
    vector<ll> sz;
    vector<set<pair<ll,ll>>> aadj;

    UnionFind(ll n) : n(n) , rep(n+5, 0), sz(n+5, 1) , aadj(n+5) {
        forn(i,0,n){
            rep[i]=i;
            for(auto j:adj[i]){
               aadj[i].insert({p[j],j});
            }
        }
    }

    ll Find(ll a){
        return rep[a]==a?a:rep[a]=Find(rep[a]);
    }

    void Union(ll a, ll b){

        debug("Union "<<a<<" "<<b<<'\n');

        ll pa = Find(a);
        ll pb = Find(b);

        if(pa==pb) return;

        if(sz[pa]<sz[pb]){
            rep[pa]=pb;
            for(auto i:aadj[pa]) aadj[pb].insert(i);
        }else{
            rep[pb]=pa;
            if(sz[pa]==sz[pb]){
                sz[pa]++;
            }
            for(auto i:aadj[pb]) aadj[pa].insert(i);
        }
    }
};

ll toJ;
ll lvlToJ;

ll lvl[MAXN];
ll pa[MAXN];
ll blift[MAXN][MAXP];

void dfs(ll nd, ll p, ll lv){
    lvl[nd]=lv;
    pa[nd]=p;
    for(auto i:adj[nd]) if(i!=p){
        dfs(i,nd,lv+1);
    }
}

void precalc(){
    forn(i,0,n) blift[i][0]=pa[i];

    forn(k,1,MAXP){
        forn(i,0,n){
            if(blift[i][k-1]!=-1) blift[i][k]=blift[blift[i][k-1]][k-1];
            else blift[i][k]=-1;
        }
    }
}

void sameLvl(ll &a, ll &b){
    if(lvl[a]>lvl[b]) swap(a,b);

    for(int k = MAXP-1; k>=0; k--){
        if(blift[b][k]!=-1 && lvl[blift[b][k]]>=lvl[a]){
            b=blift[b][k];
        }
    }
}

ll LCA(ll a, ll b){
    sameLvl(a,b);

    for(int k = MAXP-1; k>=0; k--){
        if(blift[a][k]!=blift[b][k]){
            a=blift[a][k];
            b=blift[b][k];
        }
    }
    if(a==b) return a;
    return pa[a];
}

int main(){
    
    mset(res,0);

    cin>>n;
    forn(i,0,n) cin>>p[i];

    ll u,v;
    forn(i,0,n-1){
        cin>>u>>v; u--; v--;
        adj[u].pb(v);
        adj[v].pb(u);
    }

    vector<pair<ll,ll>> ord;
    forn(i,0,n){
        ord.pb({p[i],i});
    }
    sort(ALL(ord));

    dfs(0,-1,0);
    precalc();

    UnionFind uf(n);

    forn(i,0,n-1){
        toJ=-1;
        lvlToJ=-1;

        ll nd = ord[i].snd;
        ll val = ord[i].fst;

        for(auto j:adj[nd]) if(p[j]<p[nd]){
            uf.Union(nd,j);
        }

        ll rep = uf.Find(nd);
        toJ = uf.aadj[rep].lower_bound({val+1,0})->snd;

        ll lca = LCA(nd,toJ);
        lvlToJ=(lvl[nd]-lvl[lca]) + (lvl[toJ]-lvl[lca]);

        debug(i<<" "<<nd<<" "<<toJ<<" "<<rep<<" "<<lvlToJ<<'\n');
        debug(res[nd]<<'\n');

        res[toJ]=max(res[toJ], res[nd]+lvlToJ);
    }

    cout<<res[ord.back().snd]<<'\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...