zoukankan      html  css  js  c++  java
  • 天天爱跑步

    题目链接:Click here

    Solution:

    首先orz@WYBIACX,蒟蒻本来不怎么会,看了大佬题解才会

    写完这题后有所收获,所以特此总结一下

    对于每条路径,我们可以把它拆成(u ightarrow lca(u,v))(lca(u,v) ightarrow v)来考虑

    对于(u ightarrow lca)这条路径上的点(x),显然仅当(dep[x]+w[x]=dep[u])时,(u)才会对(x)造成造成贡献

    则第一次计算,我们对一个点,定义它的权值为(dep[x]),用一个桶去维护数量

    对于(lca ightarrow v)这条路经上的点,首先就可以得出当(dis(u,x)=w[x])时,(u)(x)可以造成贡献

    但是我们如果直接这样算,是无法利用桶去维护的,则考虑如何转化

    (dis(u,x)-dep[x]=w[x]-dep[x])(dis(u,v)-dep[v]=w[x]-dep[x])

    则对于(lca ightarrow v)这条路径上的点,当(dis(u,v)-dep[v]=w[x]-dep[x])时有贡献,我们同样用一个桶来维护

    要注意的是一条路径是不能对他们(lca)以上的点造成影响的,所以要在他们的(lca)处在桶内减掉他们

    还有,当(lca)可以观测到这条路径上的点时,它会被算两次,我们应该减去多算的

    最后,桶的下标并不一定是正数,所以我们要把下标值加上(maxn)

    Code:

    #include<bits/stdc++.h>
    const int N=3e5+11;
    using namespace std;
    int n,m,cnt,head[N],w[N],fa[N];
    int son[N],sz[N],dep[N],ans[N];
    int num[N],top[N],bucket[N*3];
    vector<int> v1[N],v2[N],v3[N];
    struct Edge{int nxt,to;}edge[N<<1];
    int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
        return x*f;
    }
    void ins(int x,int y){
        edge[++cnt].nxt=head[x];
        edge[cnt].to=y;head[x]=cnt;
    }
    void dfs1(int x,int fat){
        for(int i=head[x];i;i=edge[i].nxt){
            int y=edge[i].to;
            if(y==fat) continue;
            fa[y]=x;dep[y]=dep[x]+1;
            dfs1(y,x);sz[x]+=sz[y];
            if(sz[y]>sz[son[x]]) son[x]=y;
        }++sz[x];
    }
    void dfs2(int x,int topx){
        top[x]=topx;
        if(!son[x]) return ;
        dfs2(son[x],topx);
        for(int i=head[x];i;i=edge[i].nxt){
            int y=edge[i].to;
            if(y==fa[x]||y==son[x]) continue;
            dfs2(y,y);
        }
    }
    int Lca(int x,int y){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            x=fa[top[x]];
        }return dep[x]<dep[y]?x:y;
    }
    int dis(int x,int y){
        return dep[x]+dep[y]-(dep[Lca(x,y)]<<1);
    }
    void calc1(int x){
        int pre=bucket[dep[x]+w[x]+N];
        for(int i=head[x];i;i=edge[i].nxt){
            int y=edge[i].to;
            if(y==fa[x]) continue;
            calc1(y);
        }
        bucket[dep[x]+N]+=num[x];
        ans[x]+=bucket[dep[x]+w[x]+N]-pre;
        for(int i=0;i<v1[x].size();i++)
            --bucket[dep[v1[x][i]]+N];
    }
    void calc2(int x){
        int pre=bucket[w[x]-dep[x]+N];
        for(int i=head[x];i;i=edge[i].nxt){
            int y=edge[i].to;
            if(y==fa[x]) continue;
            calc2(y);
        }
        for(int i=0;i<v3[x].size();i++)
            ++bucket[dis(x,v3[x][i])-dep[x]+N];
        ans[x]+=bucket[w[x]-dep[x]+N]-pre;
        for(int i=0;i<v2[x].size();i++)
            --bucket[v2[x][i]+N];
    }
    signed main(){
        n=read(),m=read();
        for(int i=1;i<n;i++){
            int x=read(),y=read();
            ins(x,y),ins(y,x);
        }
        for(int i=1;i<=n;i++) w[i]=read();
        dfs1(1,0);dfs2(1,1);
        for(int i=1;i<=m;i++){
            int x=read(),y=read();
            num[x]++;int lca=Lca(x,y);
            v1[lca].push_back(x);
            v2[lca].push_back(dis(x,y)-dep[y]);
            v3[y].push_back(x);
            if(dep[lca]+w[lca]==dep[x]) --ans[lca];
        }
        calc1(1);calc2(1);
        for(int i=1;i<=n;i++)
            printf("%d ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    location.href使用方法总结
    Ubuntu 12.04 安装JDK 8和Eclipse
    【一】仿微信飞机大战cocos2d-x3.0rc1
    QTP的基本功能介绍
    Spring+Ibatis集成开发实例
    Java NIO与IO的差别和比較
    嵌入式Linux常见问题
    递归和迭代之间的差
    大约sources.list和apt-get [转载]
    JVM学习笔记(一)------的基本结构
  • 原文地址:https://www.cnblogs.com/NLDQY/p/11527956.html
Copyright © 2011-2022 走看看