点分治模板

1.选取树的重心p
2.从p出发进行DFS,求得所需的数组
3.执行cal(p)
4.删除p结点,对p的每颗子树(无根树)递归执行1~4步
此算法在蓝书中亦有记载

vector<pii>e[maxn];
int sz[maxn];
int vis[maxn];
int dp[maxn];
int k;
int n;
int ans=0;
int root=0;
void getSz(int u,int fa){
    sz[u]=1;
    for(auto[v,w]:e[u]){
        if(vis[v]||fa==v)continue;
        getSz(v,u);
        sz[u]+=sz[v];
    }
}
void find(int u,int fa,int tot){
    sz[u]=1;
    dp[u]=0;
    for(auto[v,w]:e[u]){
        if(vis[v]||v==fa)continue;
        find(v,u,tot);
        sz[u]+=sz[v];
        dp[u]=max(dp[u],sz[v]);
    }
    dp[u]=max(dp[u],tot-sz[u]);
    if(dp[u]<dp[root])root=u;
}
void collect(int u,int fa,int dis,vector<int>&d){
    d.pb(dis);
    for(auto[v,w]:e[u]){
        if(vis[v]||v==fa)continue;
        collect(v,u,dis+w,d);
    }
}
int cal(vector<int>&d){
    sort(d.begin(),d.end());
    int cnt=0;
    int l=0,r=d.size()-1;
    while(l<r){
        if(d[l]+d[r]<=k){
            cnt+=r-l;
            l++;
        }else r--;
    }
    return cnt;
}
void work(int u,int tot){
    if(tot<=1)return;
    int G=u;
    find(u,-1,tot);
    vis[G]=1;
    vector<int>path={0};
    for(auto[v,w]:e[G]){
        if(vis[v])continue;
        vector<int>sub;
        collect(v,G,w,sub);
        ans-=cal(sub);
        for(auto s:sub)path.pb(s);
    }
    ans+=cal(path);
    for(auto[v,w]:e[G]){
        if(vis[v])continue;
        int size=sz[v];
        work(v,size);
    }
}```
posted @ 2025-09-30 20:40  Marinaco  阅读(15)  评论(0)    收藏  举报
//雪花飘落效果