• [模板] 点分治


    以树的重心为根,划分树上路径,考虑两段路径相连产生的影响。

    luogu的AC代码、题解很多都有问题,其siz并不正确,然而这样的代码跑得比正确的快,很难受。

    应该在每次求得root后再求一次siz数组,才能保证分治的log

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    inline int rd(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    const int MAXN=100005;
    
    struct Edge{
        int next,to,w;
    }e[MAXN<<1];
    int ecnt,head[MAXN];
    inline void add(int x,int y,int w){
        e[++ecnt].next = head[x];
        e[ecnt].to = y;
        e[ecnt].w = w;
        head[x] = ecnt;
    }
    
    int n,m;
    
    int ask[MAXN];
    
    bool vis[MAXN];
    int root,siz[MAXN],mn;
    void getsiz(int x,int pre){
        siz[x]=1;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]||v==pre) continue;
            getsiz(v,x);
            siz[x]+=siz[v];
        }
    }
    
    void getroot(int x,int pre,int sum){
        int mx=0;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]||v==pre) continue;
            mx=max(mx,siz[v]);
            getroot(v,x,sum);
        }
        mx=max(mx,sum-siz[x]);
        if(mx<mn) mn=mx,root=x;
    }
    
    bool f[10000005];
    int s[MAXN],sav[MAXN],ans[MAXN];
    
    void dfs(int x,int pre,int dis){
        s[++s[0]]=dis;sav[++sav[0]]=dis;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]||v==pre) continue;
            dfs(v,x,dis+e[i].w);
        }
    }
    
    void dac(int x){
        f[0]=1;sav[0]=0;
        mn=n;
        getsiz(x,-1);
        getroot(x,-1,siz[x]);
        vis[root]=1;
        for(int i=head[root];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]) continue;
            s[0]=0;dfs(v,x,e[i].w);
            for(int k=s[0];k>=1;k--){
                for(int j=1;j<=m;j++){
                    if(s[k]>ask[j]) continue;
                    ans[j]|=f[ask[j]-s[k]];
                }
            }
            for(int k=s[0];k>=1;k--)f[s[k]]=1;
        }
        for(int i=sav[0];i>=1;i--) f[sav[i]]=0;
        int u=root;
        for(int i=head[u];i;i=e[i].next) {
            int v=e[i].to;
            if(!vis[v]) dac(v);
        }
    }
    
    int main(){
        n=rd();m=rd();
        int x,y,w;
        for(int i=1;i<n;i++){
            x=rd();y=rd();w=rd();
            add(x,y,w);add(y,x,w);
        }    
        for(int i=1;i<=m;i++) ask[i]=rd();
        dac(1);
        for(int i=1;i<=m;i++) ans[i]?puts("AYE"):puts("NAY");
        return 0;
    }

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9474942.html

  • 相关阅读:
    阅读编程书籍的方法(转)
    Java 面向对象概念
    Python 统计文本中单词的个数
    Python 学习笔记(五)杂项
    在CentOS7环境下部署TiDB
    前端学习之路:第三章、来做个天气应用吧(1)
    前端学习之路:第二章、Vue-router和axios
    前端学习之路:第一章、开始使用Vue
    在Docker下搭建Apache+PHP+mysql环境的过程记录
    在基于Windows系统的PHP后端中引入Redis
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9474942.html
Copyright © 2020-2023  润新知