HDU 6162 Ch’s gift(LCA 暴力 17多校第九场)

来源:互联网 发布:卖家怎么开淘宝客 编辑:程序博客网 时间:2024/06/06 01:11
  • 题目大意

    给你一颗n个节点的树,每个节点有一个权值,给出m组询问,每次询问对于给定的一个点对(a,b),问你a,b两个点的最短路径上点权值在[L,R]内的和是多少
    1n,m105

  • 分析

    这道题数据范围比较小(数据比较弱),直接暴力从两个点出发一步一步往上走直到相遇统计路径上满足条件的点权和即可
    官方题解给出了树链剖分的思路,有空再补吧

  • 代码

#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<cstdlib>#include<queue>#include<map>#include<algorithm>#include<set>#include<stack>using namespace std;#define  LL long long intconst int INF=0x3f3f3f3f;const int MAXN=200005;int n,m;LL value[MAXN];int depth[MAXN];int vis[MAXN];int fa[MAXN];LL ans[MAXN];struct Edge{    int v;    int next;}edge[MAXN*4];int edgecount;int head[MAXN];void Init(){    edgecount=0;    memset(head,-1,sizeof(head));    memset(depth,0,sizeof(depth));    memset(vis,0,sizeof(vis));}void Add_edge(int u,int v){    edge[++edgecount].v=v;    edge[edgecount].next=head[u];    head[u]=edgecount;}void Dfs(int u)//搜索求出每个点的父亲{    for(int k=head[u];k!=-1;k=edge[k].next)    {        int v=edge[k].v;        if(vis[v]==0){fa[v]=u;vis[v]=1;depth[v]=depth[u]+1;Dfs(v);}    }}LL LCA(int s,int t,int a,int b){    LL ans=0;    if(value[s]>=a && value[s]<=b)ans+=value[s];    if(value[t]>=a && value[t]<=b)ans+=value[t];    while(depth[s]<depth[t])    {        t=fa[t];        if(value[t]>=a && value[t]<=b)ans+=value[t];    }    while(depth[s]>depth[t])    {        s=fa[s];        if(value[s]>=a && value[s]<=b)ans+=value[s];    }    while(s!=t)    {        t=fa[t];        s=fa[s];        if(value[s]>=a && value[s]<=b)ans+=value[s];        if(value[t]>=a && value[t]<=b)ans+=value[t];    }    if(value[s]>=a && value[s]<=b)ans-=value[s];    return ans;}int main(){    int s,t,a,b;    while(scanf("%d%d",&n,&m)!=EOF)    {        Init();        for(int i=1;i<=n;i++)scanf("%lld",&value[i]);        for(int i=1;i<n;i++)        {            scanf("%d%d",&a,&b);            Add_edge(a,b);            Add_edge(b,a);        }        int root=n/2;        fa[root]=0;        vis[root]=1;        Dfs(root);        for(int i=1;i<=m;i++)        {            scanf("%d%d%d%d",&s,&t,&a,&b);            ans[i]=LCA(s,t,a,b);        }        for(int i=1;i<m;i++)printf("%lld ",ans[i]);        printf("%lld\n",ans[m]);    }    return 0;}/*5 21 2 1 3 21 22 43 12 53 5 1 35 3 1 3*/
原创粉丝点击