zoukankan      html  css  js  c++  java
  • P3806 【模板】点分治1

    题目

    P3806 【模板】点分治1

    定一棵有 (n) 个点的树,多次询问树上距离为 (k) 的点对是否存在。

    分析

    淀粉质模板题。

    淀粉质的核心就是其只统计经过当前根结点的路径,即可以把两条路径“拼”起来,同时分治结构保证了其只有 (log) 次这样的计算。

    常用于统计树上点对数量这样的问题。

    来看这道题。

    可以对每一个路径长度开一个桶来存有多少条,但是这里是多次询问,于是我们每一次要遍历所有询问来查找桶。

    具体可以见代码:

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
        x=0;char ch=getchar();bool f=false;
        while(!isdigit(ch)) f|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;return;
    }
    template <typename T>
    inline void write(T x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10^48);return;
    }
    #define ll long long
    const int N=1e5+5,M=1e7+5;
    int n,m;
    int head[N],nex[N],to[N],val[N],idx;
    bool vis[N],Vis[N],app[M],Ans[N];
    int Q[N],path[N],clear[N],siz[N];
    int Root,NowMax,path_cnt,Cnt,Size;
    inline void add(int u,int v,int w){
    	nex[++idx]=head[u];
    	to[idx]=v;
    	val[idx]=w;
    	head[u]=idx;
    	return ;
    }
    void FindRoot(int x){
    	vis[x]=true;siz[x]=1;int Max=0;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(vis[y]||Vis[y]) continue;
    		FindRoot(y);siz[x]+=siz[y];
    		Max=max(siz[y],Max);
    	}
    	Max=max(Size-siz[x],Max);
    	if(Max<NowMax) NowMax=Max,Root=x;
    	vis[x]=false;
    	return ;
    }
    void GetPath(int x,int D){
    	path[++path_cnt]=D;vis[x]=true;siz[x]=1;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(vis[y]||Vis[y]) continue;
    		GetPath(y,D+val[i]);siz[x]+=siz[y];
    	}
    	vis[x]=false;
    	return ;
    }
    void DFS(int x){
    	Vis[x]=true;Cnt=0;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(Vis[y]) continue;
    		path_cnt=0;GetPath(y,val[i]);
    		for(int j=1;j<=m;j++){
    			for(int k=1;k<=path_cnt;k++){
    				if(Q[j]>=path[k]&&app[Q[j]-path[k]]) Ans[j]=true;
    			}
    		}
    		for(int j=1;j<=path_cnt;j++) if(path[j]<M) app[path[j]]=true,clear[++Cnt]=path[j];
    	}
    	for(int i=1;i<=Cnt;i++) app[clear[i]]=false;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(Vis[y]) continue;
    		Size=siz[y],NowMax=n,Root=0,FindRoot(y);DFS(Root);
    	}
    	return ;
    }
    
    signed main(){
    	read(n),read(m);
    	for(int i=1;i<n;i++){
    		int u,v,w;
    		read(u),read(v),read(w);
    		add(u,v,w),add(v,u,w);
    	}
    	app[0]=true;
    	for(int i=1;i<=m;i++) read(Q[i]); 
    	Size=n,NowMax=n,Root=0,FindRoot(1),DFS(Root);
    	for(int i=1;i<=m;i++) puts(Ans[i]?"AYE":"NAY");
    	return 0;
    }
    
  • 相关阅读:
    LeetCode 295. Find Median from Data Stream (堆)
    LeetCode 292. Nim Game(博弈论)
    《JavaScript 模式》读书笔记(4)— 函数2
    《JavaScript 模式》读书笔记(4)— 函数1
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数3
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数2
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数1
    《JavaScript 模式》读书笔记(2)— 基本技巧3
    《JavaScript 模式》读书笔记(2)— 基本技巧2
    《JavaScript 模式》读书笔记(2)— 基本技巧1
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14726790.html
Copyright © 2011-2022 走看看