Submission #1207470

#TimeUsernameProblemLanguageResultExecution timeMemory
1207470lightonJOI tour (JOI24_joitour)C++20
30 / 100
3035 ms78540 KiB
#include "joitour.h"
#include<bits/stdc++.h>
#define pb push_back
#define all(v) v.begin(),v.end()
#define forf(i,s,e) for(int i = s; i<=e; i++)
#define forb(i,s,e) for(int i = s; i>=e; i--)
#define idx(i,v) lower_bound(all(v),i)-v.begin()
#define comp(v) v.erase(unique(all(v)),v.end())
#define sz(v) (int)v.size()
#define fs first
#define se second
#define SP << " " <<
#define LN << "\n"
#define IO cin.tie(0);cout.tie(0);ios_base::sync_with_stdio(false);
using namespace std;
typedef long long ll;
ll inf = 1e18;

int N;
int C[200001];
vector<int> adj[200001];

vector<int> c_ch[200001];
int c_par[200001],c_dep[200001],c_chidx[200001];
int sz[200001], chk[200001], pth[200001];
ll subsum[200001][3][3];
ll dp[200001][3][3];
int getsz(int now, int p = -1){
    sz[now] = 1;
    for(int &i : adj[now]) if(i!=p && !chk[i]) sz[now]+=getsz(i,now);
    return sz[now];
}
int getcent(int now, int p, int cap, int d){
    if(d!= -1) pth[now] = d;
    for(int &i : adj[now]) if(i!=p && !chk[i] && sz[i]*2>cap) return getcent(i,now,cap,d);
    return now;
}
int centdecom(int now, int par, int d = 1){
    //now = getcent(now,-1,getsz(now),-1);
    c_chidx[now] = -1;
    c_dep[now] = d;
    chk[now] = 1;
    for(int &i : adj[now]){
        if(!chk[i]){
            /*int cent = getcent(i,-1,getsz(i),-1);
            if(pth[i] == d) {
                assert(c_chidx[now] == -1);
                c_chidx[now] = cent;
            }
            cent = getcent(i,-1,getsz(i),d+1);*/
            int cent = i;
            c_par[cent] = now;
            c_ch[now].pb(cent);
            int cent2 = centdecom(i,par,d+1);
            assert(cent==cent2);
        }
    }
    return now;
}

int cent;
ll ans[200001][3];
ll rans = 0;

void ansupd(ll now, ll f){
    forf(i,0,2) {
        ans[now][i] += subsum[now][0][1] * subsum[now][2][2] * f;
        ans[now][i] += subsum[now][0][0] * subsum[now][2][1] * f;
    }
    ans[now][0] += subsum[now][2][1]*f;
    ans[now][1] += subsum[now][0][0]*subsum[now][2][2]*f;
    ans[now][2] += subsum[now][0][1]*f;
}

void ansupd2(ll now, ll f){
    int par = c_par[now];
    if(par == -1) return;
    forf(i,0,2) {
        ans[par][i] -= dp[now][0][1] * dp[now][2][2] * f;
        ans[par][i] -= dp[now][0][0] * dp[now][2][1] * f;
    }
    ans[par][1] -= dp[now][0][0]*dp[now][2][2]*f;
}

void upd(int now, int to){
    int par = c_par[now];
    int ch = c_chidx[now];

    if(par != -1) ansupd(par,-1),ansupd2(now,-1);
    if(par != -1) forf(i,0,2) forf(j,0,2) subsum[par][i][j] -= dp[now][i][j];
    C[now] = to;

    forf(i,0,2) dp[now][i][i] = subsum[now][i][i] + ((C[now]==i)?1:0);
    forf(i,0,2) forf(j,0,2) {
        if(i==j) continue;
        dp[now][i][j] = subsum[now][i][j];
        if (ch != -1){
            dp[now][i][j] += (-dp[ch][i][j]+dp[ch][j][i]);
            dp[now][i][j] += dp[ch][j][j] * (dp[now][i][i]-dp[ch][i][i]);
        }
        if (C[now]==j){
            dp[now][i][j] += subsum[now][i][i];
            if(ch != -1) dp[now][i][j] -= dp[ch][i][i];
        }
    }

    if(par != -1) forf(i,0,2) forf(j,0,2) subsum[par][i][j] += dp[now][i][j];
    if(par != -1) upd(par,C[par]);
    if(par != -1) ansupd(par,1),ansupd2(now,1);
}

void ini(int now){
    for(auto i : c_ch[now]){
        ini(i);
        subsum[now][0][0] += dp[i][0][0];
    }
    dp[now][0][0] = subsum[now][0][0] +1;
}

void go(int x, int y){
    int now = x; while(now != -1) rans -= ans[now][C[now]], now = c_par[now];
    upd(x,y);
    now = x; while(now != -1) rans += ans[now][C[now]], now = c_par[now];
}

void init(int N, std::vector<int> F, std::vector<int> U, std::vector<int> V,
          int Q) {
    ::N = N;
    forf(i,0,N-2) adj[U[i]].pb(V[i]) ,adj[V[i]].pb(U[i]);
    cent = centdecom(0,-1,1); c_par[cent] = -1;
    ini(cent);
    forf(i,0,N-1) go(i,F[i]);
}

void change(int X, int Y) {
    go(X,Y);
}

long long num_tours() {
  return rans;
}
#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...