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]);
    }
  • 相关阅读:
    UVa 116 单向TSP(多段图最短路)
    POJ 1328 Radar Installation(贪心)
    POJ 1260 Pearls
    POJ 1836 Alignment
    POJ 3267 The Cow Lexicon
    UVa 1620 懒惰的苏珊(逆序数)
    POJ 1018 Communication System(DP)
    UVa 1347 旅行
    UVa 437 巴比伦塔
    UVa 1025 城市里的间谍
  • 原文地址:https://www.cnblogs.com/00isok/p/10925674.html
Copyright © 2011-2022 走看看