zoukankan      html  css  js  c++  java
  • CF739B Alyona and a tree 树上差分

    题目描述

    Alyona有一棵有 n个节点的树。这棵树的根节点是 1。在每个节点里,Alyona写了一个正整数,在节点 i 她写了正整数a_i
    。另外,她在这棵树上的每条边上写了一个正整数(不同边上可能有不同的数)。
    让我们定义 dist(v,u) 作为从 v 到 u 的简单路径上的边权和。
    当且仅当 u 在 v 的子树中并且 dist(v,u)<=a_u,顶点 v 控制顶点 u(v!=u) 。Alyona想在某些顶点定居。为了做到这件事,她想知道在每个节点 v 能控制几个节点。

    题解

    对于(u),(v)两点,若(dis(u,v)<=a[u]),则u,v间的点都满足当前性质,即满足(u),(v)间的点都能控制(u)
    (dfs)往下扫,将(dis(u,v)<=a[u])拆成(dis[v]<=dis[u]-a[u])(vector)存当前点的(dis[x]),若子树中的点的(dis[u]-a[u])找到从根开始第一个满足该性质的点,则该点到(u)点路径中所有的点都满足要求
    然后差分做,返回的时候清除节点,用子节点更新当点节点

    #include <bits/stdc++.h>
    #define For(i,a,b) for(int i=(a);i<=(b);i++)
    #define Dec(i,a,b) for(int i=(a);i>=(b);i--)
    const int maxn=2e5+10;
    const int k=448;
    typedef long long ll;
    using namespace std;
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline ll readll(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int ans[maxn];
    ll dis[maxn],a[maxn];
    vector<ll>val[maxn];
    vector<int>G[maxn];
    vector<pair<ll,int> >que;
    //对于u,v两点,若dis(u,v)<=a[u],则u,v间的点都满足当前性质,即满足u,v间的点都能控制u
    //故dfs往下扫,将dis(u,v)<=a[u]拆成dis[v]<=dis[u]-a[u]用vector存当前点的dis[x],若子树中的点的dis[u]-a[u]找到从根开始第一个满足该性质的点,则该点到u点路径中所有的点都满足要求
    //然后差分做,返回的时候清除节点 
    void dfs(int x,int fa){
        ans[x]=1;
        ll t=dis[x]-a[x];
        int pos=lower_bound(que.begin(),que.end(),make_pair(t,0))-que.begin()-1;
        if(pos>=0)ans[que[pos].second]--;
        que.push_back(make_pair(dis[x],x));
        For(i,0,(int)G[x].size()-1){
            int u=G[x][i];
            if(u==fa)continue;
            dis[u]=dis[x]+val[x][i];
            dfs(u,x);
            ans[x]+=ans[u];
        }
        que.pop_back();
    }
    int main(){
        int n;
        n=read();
        For(i,1,n)a[i]=readll();
        int v;
        ll cost;
        For(i,2,n){
            v=read();cost=readll();
            val[i].push_back(cost);
            val[v].push_back(cost);
            G[i].push_back(v);
            G[v].push_back(i);
        }
        dfs(1,-1);
        For(i,1,n)printf("%d ",ans[i]-1);
        return 0;
    }
    
  • 相关阅读:
    .NET程序员 湖南创世纪网络
    java.lang.NoSuchMethodError:SpringJAR包版本冲突错误解决方法
    事实表和纬度表概述
    SQL Server中char、nchar、varchar、nvarchar的区别
    biztalk 2010 映射
    biztalk 2010 架构
    字符编码简单总结
    浅析组织结构与个人发展的关系
    缓慢渐变维度的处理方式
    SQL server中SET ANSI_PADDING对char、varchar、nvarchar的影响
  • 原文地址:https://www.cnblogs.com/Nan-Cheng/p/9735294.html
Copyright © 2011-2022 走看看