【BZOJ 1316】 树上的询问 树分治

原创 2017年01月03日 10:20:29

按理来说是一个非常简单的树分治,我只是为了将专题的时候作为一道引入题目的,不过,我擦set和map的常数差别有那么大吗,map居然比set慢了10倍,然后就一直T啊一直T最后看他们都用的set改过来就A了,我也是郁闷。

方法很简单,用set记录一个长度有没有出现过,然后每次树分治统计

    #include<cstdio>  
    #include<cstring>  
    #include<iostream>  
    #include<set>  
    #include<cstdlib>  
    #define maxn 30010  
    #define maxm 1000020  
    using namespace std;  
    int head[maxn],tot,dis[maxn],n,m,q[maxn],f[maxn],s[maxn],size,rt,vis[maxn],ans[maxn];  
    struct edge{int v,next,w;}e[maxn*2];  
    void adde(int a,int b,int c){e[tot].v=b,e[tot].w=c,e[tot].next=head[a];head[a]=tot++;}  
    set<int>Map;  
      
    void getrt(int u,int fa){  
        f[u]=0,s[u]=1;  
        for(int v,i=head[u];i!=-1;i=e[i].next){  
            if(vis[v=e[i].v]||v==fa)continue;  
            getrt(v,u);  
            s[u]+=s[v];  
            f[u]=max(f[u],s[v]);  
        }  
        f[u]=max(f[u],size-f[u]);  
        if(f[u]<f[rt])rt=u;  
    }  
      
    int cur[maxn*2],p;  
    void dfs(int u,int fa){  
        cur[++p]=dis[u];  
        for(int v,i=head[u];i!=-1;i=e[i].next){  
            if(vis[v=e[i].v]||v==fa)continue;  
            dis[v]=dis[u]+e[i].w;  
            dfs(v,u);  
        }  
    }  
       
    void calc(int u){  
        Map.clear();Map.insert(0);  
        for(int v,i=head[u];i!=-1;i=e[i].next){  
            if(vis[v=e[i].v])continue;  
            dis[v]=e[i].w,p=0;  
            dfs(v,u);  
            for(int j=1;j<=p;j++){  
                for(int k=1;k<=m;k++){  
                    if(Map.find(q[k]-cur[j])!=Map.end())ans[k]++;  
                }  
            }  
            for(int j=1;j<=p;j++)Map.insert(cur[j]);  
        }  
    }  
       
    void solve(int u){  
        vis[u]=1;  
        calc(u);  
        for(int i=head[u],v;i!=-1;i=e[i].next){  
            if(vis[v=e[i].v])continue;  
            f[rt=0]=size=s[v];  
            getrt(v,u);  
            solve(rt);  
        }  
    }  
       
    int main(){  
        memset(head,-1,sizeof(head));  
        scanf("%d%d",&n,&m);  
        for(int a,b,c,i=1;i<n;i++){  
            scanf("%d%d%d",&a,&b,&c);  
            adde(a,b,c),adde(b,a,c);  
        }  
        for(int i=1;i<=m;i++)scanf("%d",q+i);  
        f[rt=0]=size=n;  
        getrt(1,1);  
        solve(rt);  
        for(int i=1;i<=m;i++)if(ans[i]>0||q[i]==0)  
            puts("Yes");else puts("No");  
        return 0;  
    }  

版权声明:你喜欢就好

【bzoj1316】【树上的询问】【点分治+map】

Description 一棵n个点的带权有根树,有p个询问,每次询问树中是否存在一条长度为Len的路径,如果是,输出Yes否输出No. Input 第一行两个整数n, p分别表示点的个数...
  • sunshinezff
  • sunshinezff
  • 2016年07月08日 09:30
  • 668

[BZOJ1316]树上的询问(点分治+二分)

题目描述传送门题解点分治裸题 每一次求出deep之后排序然后两次二分 因为点分常数很大做一次求m个比做m次快得多代码#include #include #include #include #inc...
  • Clove_unique
  • Clove_unique
  • 2017年02月19日 23:10
  • 588

BZOJ3221 [Codechef FEB13] Obserbing the tree树上询问

闲来无事水一发毒瘤题 链剖+主席树即可 区间加一个等差数列标记合并的时候把首项和公差都加起来就好了 因为区间修改所以要标记永久化,除了标记以外还要记录子树内因更改所增加的和 #include ...
  • neither_nor
  • neither_nor
  • 2016年06月17日 14:47
  • 663

bzoj 1316: 树上的询问 (点分治)

1316: 树上的询问 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 564  Solved: 150 [Submit][Status][Discu...
  • clover_hxy
  • clover_hxy
  • 2017年01月13日 19:35
  • 281

BZOJ 1316: 树上的询问 点分治

1316: 树上的询问 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 691  Solved: 187 [Submit][Status][Discu...
  • BlackJack_
  • BlackJack_
  • 2017年06月20日 19:56
  • 252

BZOJ 3221 [Codechef FEB13] Obserbing the tree树上询问 树链剖分 主席树维护区间加等差数列

题目大意:给出一棵树,每个结点初始均为0,要求支持以下操作:路径加等差数列,询问路径上结点权值和,回到之前的某个版本调到吐血。很明显可以看出需要树链剖分+主席树来解决,由于需要在主席树上区间修改所以标...
  • YihAN_Z
  • YihAN_Z
  • 2017年04月02日 00:15
  • 332

BZOJ 1316: 树上的询问 点分治题解

Time Limit: 10 Sec Memory Limit: 162 MB Submit: 738 Solved: 203Description一棵n个点的带权有根树,有p个询问,每次询问树...
  • NOIAu
  • NOIAu
  • 2017年09月13日 05:57
  • 155

分治技巧在高级数据结构中的应用——线段树分治(二)&&bzoj4137火星商店问题详解

分治技巧在高级数据结构中的应用——线段树分治(二) 从一道神题说起 4137: [FJOI2015]火星商店问题 Time Limit: 20 Sec  Memory Limit: 25...
  • lvzelong2014
  • lvzelong2014
  • 2017年12月01日 17:11
  • 200

bzoj 3784: 树上的路径

Description 给定一个N个结点的树,结点用正整数1..N编号。每条边有一个正整数权值。用d(a,b)表示从结点a到结点b路边上经过边的权值。其中要求a Input ...
  • lqybzx
  • lqybzx
  • 2015年04月15日 13:40
  • 1163

bzoj2588Spoj 10628. Count on a tree 树上主席树

比较经典的树上主席树,然而改了半天,tmd发现线段树开大了导致TLE?????这TM都能T?醉了,虽然我知道开大空间可能会T,但没想到有一天自己亲身成为实验体QAQ。。跟普通的主席树其实没什么区别,就...
  • qq_35866453
  • qq_35866453
  • 2017年06月08日 21:26
  • 215
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【BZOJ 1316】 树上的询问 树分治
举报原因:
原因补充:

(最多只允许输入30个字)