zoukankan      html  css  js  c++  java
  • CodeForces 739B Alyona and a tree (二分+树上差分)

    <题目链接>

    题目大意:

    给定一颗带权树,树的根是1,树上每个点都有点权,并且还有边权。现在给出“控制”的定义:对一个点u,设v为其子树上的节点,且$dis(u,v)≤val[v]$,则称u控制v。求出每个点控制的点数。

    解题分析:

    处理出所有点到根的距离$dist$,然后任意两点之间的距离为$dist[v]-dist[u]$($v$为$u$的子树中的节点)。因为在每条链上,$dist$由根向子树深搜的过程中都是递增的,所以可以用二分快速找到能够控制当前节点的$dep$最浅的父亲节点,然后利用树上差分进行高效的个数统计。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>
    inline void read(T&x){        
        x=0;int f=1;char ch=getchar();
        while(ch<'0' ||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); }
        while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
        x*=f;
    }
    #define REP(i,s,t) for(int i=s;i<=t;i++)
    #define fi first
    #define se second
    #define pb push_back
    typedef long long ll;
    const int N = 2e5+5;
    int n,m,cnt,loc[N];
    ll val[N],dist[N],sum[N],dfn[N];
    typedef pair<int,ll>P;
    vector<P>G[N];
    //sum[i]表示每个点能够管辖的节点数
    void dfs(int u){
        dfn[++cnt]=dist[u];loc[cnt]=u;
        int cur=lower_bound(dfn+1,dfn+1+cnt,dist[u]-val[u])-dfn;//dist[v]-dist[u]<=val[v]   ===>dist[v]-val[v]<=dist[u]       //找到能够管辖这个点的深度最浅的祖先节点
        sum[loc[cur-1]]--;
        for(auto &e:G[u]){
            int v=e.fi;ll cost=e.se;
            dist[v]=dist[u]+cost;
            dfs(v);
            sum[u]+=sum[v]+1;
        }
        --cnt;    //将这个链分支中的点全部删除
    }
    int main(){
        read(n);
        REP(i,1,n)read(val[i]);
        REP(i,2,n){
            int u,w;read(u);read(w);
            G[u].pb(P(i,(ll)w));
        }
        dfs(1);
        REP(i,1,n)printf("%lld ",sum[i]);
    }
  • 相关阅读:
    [转载]每天要说无数次的话,原来英语这么说
    [转载]What I Have Lived For 一生何求?
    WIN 7 和fedora双系统引导问题
    [转载]网站建设中一些容易被忽视的问题
    linux进程控制-wait()
    shell(2)
    电脑英语缩略词
    shell(1)
    [转载]无论成败 但求做最好的自己
    [转载]C++出错提示英汉对照表
  • 原文地址:https://www.cnblogs.com/00isok/p/10925674.html
Copyright © 2011-2022 走看看