P4178 Tree 点分治
阅读原文时间:2023年07月13日阅读:1

要求权值和\(\leq K\) 的路径,我们可以类比点分治的模板,把长为\(len\)是否存在,改为\(len\)的路径的条数,并用用树状数组维护前缀和,这样就可以求出答案。

#include<bits/stdc++.h>
#define R register int
using namespace std;
namespace Luitaryi {
template<class I>    inline I g(I& x) { x=0; register I f=1;
    register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
} const int N=40010,Inf=1e9;
int n,m,cnt,tot,SZ,rt,sum,ans,K; bool vis[N];
int vr[N<<1],nxt[N<<1],w[N<<1],fir[N],d[N],sz[N],mx[N],dis[N],buf[N];
namespace BIT {
const int LIM=20000000;
int c[LIM+10];
inline void add(int p,int d) {for(;p<=LIM;p+=p&-p) c[p]+=d;}
inline int query(int p) { R ret=0;
    for(;p;p-=p&-p) ret+=c[p]; return ret;
}
}
inline void add(int u,int v,int ww) {
    vr[++cnt]=v,nxt[cnt]=fir[u],w[cnt]=ww,fir[u]=cnt;
    vr[++cnt]=u,nxt[cnt]=fir[v],w[cnt]=ww,fir[v]=cnt;
}
inline void getsz(int u,int fa) {
    sz[u]=1,mx[u]=0; for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(vis[v]||v==fa) continue;
        getsz(v,u),sz[u]+=sz[v];
        mx[u]=max(mx[u],sz[v]);
    } mx[u]=max(mx[u],sum-sz[u]);
    if(mx[u]<mx[rt]) rt=u;
}
inline void getdis(int u,int fa) { dis[++tot]=d[u];
    for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(vis[v]||v==fa) continue;
        d[v]=d[u]+w[i],getdis(v,u);
    }
}
inline void solve(int u,int fa) {
    SZ=0,BIT::add(1,1),buf[++SZ]=0,vis[u]=true;
    for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(v==fa||vis[v]) continue;
        d[v]=w[i]; getdis(v,u);
        for(R k=1;k<=tot;++k) if(K>=dis[k]) ans+=BIT::query(K-dis[k]+1);
        for(R k=1;k<=tot;++k) buf[++SZ]=dis[k],BIT::add(dis[k]+1,1);
        tot=0;
    } while(SZ) BIT::add(buf[SZ]+1,-1),--SZ;
    for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(v==fa||vis[v]) continue;
        sum=sz[v]; rt=0,mx[0]=Inf;
        getsz(v,u),getsz(rt,-1); solve(rt,u);
    }
}
inline void main() {
    g(n); for(R i=1,u,v,w;i<n;++i) g(u),g(v),g(w),add(u,v,w);
    g(K); sum=n,mx[0]=Inf; getsz(1,-1),getsz(rt,-1);
    solve(rt,-1); printf("%d\n",ans);
}
} signed main() {Luitaryi::main(); return 0;}

2019.08.31

69

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章