点分治练习1——P4178 Tree

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Love_mona/article/details/81278633

蒟蒻的垂死挣扎

我好像有很久没有更博了。。。。不过觉得自己还是要记录一下的。

点分治支持在树上的询问操作,更多的是支持树上符合要求的路径的统计,形如 树上......的路径有多少 的问题一般就是点分治能解决的问题。

原理是每次处理出子树的重心,这样子树大小最少除以二,保证时间复杂度,然后强制统计经过重心的路径,保证程序的正确性。

这题可以说是模板题了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define MOD 998244353
#define N 40010
#define M 10001000
#define RG register

using namespace std;

inline int read(){
    RG int x=0,o=1; RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') o=-1,ch=getchar();
    while(ch>='0'&&ch<='9') x=((x<<3)+(x<<1))+ch-'0',ch=getchar();
    return x*o;
}

int n,Dis,top,first[N],dis[N],root,Max,Son,Siz,siz[N],vis[N],st[N],tot;
struct mona { int nxt,en; int w; } s[N<<1];
inline void Insert(int x,int y,int w) { s[++top]=(mona) { first[x],y,w },first[x]=top; }

inline void Getroot(int k,int fa){
    siz[k]=1;   int mmax=0;
    for(RG int i=first[k];i;i=s[i].nxt){
        int en=s[i].en; if(en==fa||vis[en]) continue ;
        Getroot(en,k),siz[k]+=siz[en],mmax=max(mmax,siz[en]);
    }   mmax=max(mmax,Siz-siz[k]);
    if(Max>mmax) Max=mmax,root=k;   
}
inline void Getdis(int k,int fa,int w){
    st[++tot]=w;
    for(RG int i=first[k];i;i=s[i].nxt){
        int en=s[i].en; if(en==fa||vis[en]) continue ;
        Getdis(en,k,w+s[i].w);
    }   return ;
}
inline int Calc(int k,int ad){
    tot=0,memset(st,0,sizeof(st)),Getdis(k,0,ad),sort(st+1,st+1+tot);
    int le=1,ri=tot,ans=0;
    while(le<=ri){
        if(st[le]+st[ri]>Dis) --ri;
        else ans+=ri-le,++le;
    }   return ans;
}   int tans;
inline void Divide(int k){ //cout<<"Root "<<root<<endl;
    tans+=Calc(k,0),vis[k]=1;
    for(RG int i=first[k];i;i=s[i].nxt){
        int en=s[i].en; if(vis[en]) continue ;
        tans-=Calc(en,s[i].w);

//		Siz= (siz[k] >= siz[en]) ? siz[en] : Siz - siz[k];
        Siz=siz[en];
        Max=1e9;
        root=0,Getroot(en,0),Divide(root); 
    }
}

int main(){
    n=read();
    for(RG int i=1;i<n;++i){
        int x=read(),y=read(),z=read();
        Insert(x,y,z),Insert(y,x,z);
    }   Dis=read(),Max=1e9,Siz=n;
    Getroot(1,0),Divide(root);
    printf("%d\n",tans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Love_mona/article/details/81278633
今日推荐