實作練習

樹鏈剖分

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1E5+10;
vector<int> G[MAXN];
int cnt=0, sz[MAXN], link[MAXN], big[MAXN], dep[MAXN], fa[MAXN], arr[MAXN];
//link[x] = 所屬樹鏈的頂端, big[x] = 最大的子節點, arr[x] = 壓平序列的編號
void dfs(int x, int f){
    sz[x]=1;
    fa[x]=f;
    big[x]=-1;
    dep[x]=dep[f]+1;
    for(int i:G[x]){
        if(i==f) continue;
        dfs(i,x);
        sz[x]+=sz[i];
        if(big[x]==-1||sz[i]>sz[big[x]]){
            big[x]=i;
        }
    }
}
void getlink(int x, int top){
    link[x]=top;
    arr[x]=cnt++;
    if(big[x]!=-1) getlink(big[x],top);
    for(int i:G[x]){
        if(i==fa[x]||i==big[x]) continue;
        getlink(i,i);
    }
}

重心剖分

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1E5+10;
vector<int> G[MAXN];
int sz[MAXN], centree[MAXN];
//centree[x] = 重心樹上的父節點
bool visited[MAXN];
void getsz(int x, int f){
    sz[x]=1;
    for(int i:G[x]){
        if(visited[i]||i==f) continue;
        getsz(i,x);
        sz[x]+=sz[i];
    }
}
int findcentroid(int x, int f, int s){
    for(int i:G[x]){
        if(2*sz[i]>=s&&i!=f&&!visited[i]){
            return findcentroid(i,x,s);
        }
    }
    return x;
}
void getcentree(int x, int f){
    getsz(x,f);
    int cent=findcentroid(x,f,sz[x]);
    centree[x]=f;
    visited[cent]=1;
    for(int i:G[cent]){
        if(!visited[i]) getcentree(i,cent);
    }
}

感謝8e7 & IOIC講義提供模板

Made with Slides.com