[学习笔记]点分治

壹、模板测试连接

传送门 to LUOGU

贰、具体分析

留坑,待补。

叁、代码

using namespace Elaina;

const int inf=0x3f3f3f3f;
const int maxn=1e4;
const int maxm=100;
const int maxk=1e7;

struct edge{int to,nxt,w;;
	edge(){}
	edge(const int T,const int N,const int W):to(T),nxt(N),w(W){}
}e[maxn*2+5];
int tail[maxn+5],ecnt;
inline void add_edge(const int u,const int v,const int w){
    e[ecnt]=edge(v,tail[u],w);tail[u]=ecnt++;
    e[ecnt]=edge(u,tail[v],w);tail[v]=ecnt++;
}

int n,m;

int q[maxm+5],ans[maxm+5];

inline void input(){
    n=readin(1),m=readin(1);
    memset(tail+1,-1,sizeof(tail[0])*n);
    int u,v,w;
    rep(i,1,n-1){
        u=readin(1),v=readin(1),w=readin(1);
        add_edge(u,v,w);
    }
    rep(i,1,m)q[i]=readin(1);
}

/* record the maximum size of it's sons */ ;
int f[maxn+5];
/* use to calculate f[] */ ;
int siz[maxn+5];
/* whether this node has been a gravity center*/ ;
int use[maxn+5];

void findrt(const int u,const int par,const int n,int& root){
    siz[u]=1,f[u]=0;
    for(int i=tail[u],v;~i;i=e[i].nxt)if((v=e[i].to)!=par && !use[v]){
        findrt(v,u,n,root);
        siz[u]+=siz[v],f[u]=Max(f[u],siz[v]);
    }
    f[u]=Max(f[u],n-siz[u]);
    if(f[u]<f[root])root=u;
}

int cur[maxn+5],dis[maxn+5],ed;
/**
 * @brief while get the dis from other point to the current root, recalculate the size
*/
void getdis(const int u,const int par){
	siz[u]=1;
	cur[++ed]=dis[u];
    for(int i=tail[u],v;~i;i=e[i].nxt)if(!use[v=e[i].to] && v!=par){
        dis[v]=dis[u]+e[i].w;
        getdis(v,u);
        siz[u]+=siz[v];
    }
}
int exist[maxk+5],cls[maxn+5];
void solve(const int u){
    int clscnt=1; // exist[0] should also be cleared
	exist[0]=1;
    for(int i=tail[u],v;~i;i=e[i].nxt)if(!use[v=e[i].to]){
        ed=0,dis[v]=e[i].w; getdis(v,u);
        
        for(int j=1;j<=ed;++j)for(int k=1;k<=m;++k)
        	if(q[k]>=cur[j])ans[k]|=exist[q[k]-cur[j]];
        
        for(int j=1;j<=ed;++j)if(cur[j]<=maxk){
        	cls[++clscnt]=cur[j];
        	exist[cur[j]]=1;
		}
    }
    for(int i=1;i<=clscnt;++i)exist[cls[i]]=0;
}

void launch(const int u,const int v);
void divide(const int u){
    use[u]=1,solve(u);
    for(int i=tail[u],v;~i;i=e[i].nxt)if(!use[v=e[i].to]){
    	// the reason we can use siz is we've recalculate siz[] while invoking solve(u)
        launch(v,siz[v]);
    }
}
/**
 * @brief solve the subtre (represented by node @p u )
 * @param u the current node, represent it's subtre
 * @param n the number of the nodes of the subtre
*/
void launch(const int u,const int n){
    int root=0;f[0]=inf;
    findrt(u,0,n,root);
    divide(root);
}

signed main(){
	input();
    launch(1,n);
    rep(i,1,m)if(ans[i])printf("AYE\n");
    	else printf("NAY\n");
	return 0;
}
posted @ 2021-02-17 22:10  Arextre  阅读(31)  评论(0编辑  收藏  举报