题目描述

给出以1号点为根的一棵有根树,问每个点的子树中与它距离小于等于l的点有多少个。

输入格式

Line 1: 2 integers, N and L (1 <= N <= 200,000, 1 <= L <= 10^18)

Lines 2..N: The ith line contains two integers p_i and l_i. p_i (1 <= p_i < i) is the first pasture on the shortest path between pasture i and the barn, and l_i (1 <= l_i <= 10^12) is the length of that path.

输出格式

Lines 1..N: One number per line, the number on line i is the number pastures that can be reached from pasture i by taking roads that lead strictly farther away from the barn (pasture 1) whose total length does not exceed L.


这道题有很多高级的做法,但是我都不会

我们分析题目可以得出这样一条结论——对于当前节点u,u的子树中与u的距离大于l的点与u的所有祖先的距离都大于l(u也是自己的祖先)。所以不难想到我们对于每个节点u,我们计算出u的第一个与它距离大于l的祖先anc,那么对于这个祖先,它的答案就要减去size(u)。size表示子树的节点数,初始化每个点的答案为子树的节点数。然后结合之前得到的性质,我们可以用树上前缀和的思想,把这个减去的size(u)累加到anc的祖先中去。

但是你会发现,直接算是有问题的。

首先对于u,它对anc的答案做了值为-size(u)的贡献,并且我们要将这个贡献累加到anc的祖先中去。然后我们发现,对于u的祖先,比如u的父亲fa(u),第一个与fa(u)距离大于l的祖先也必定是anc的祖先,但我们将-size(fa(u))加到了这个祖先中,也就是说这个祖先的答案累加了两次-size(u),答案显然是错的。如何避免呢?很简单,我们将size(fa(u))减去size(u)即可。那么问题就解决了。

对于求第一个距离大于l的祖先,我们可以用倍增来做,那么总的时间复杂度就是O(NlogN)。

*由于size(fa(u))减去的是size(u)原本的大小,而此时size(u)可能已经被u的子节点减去了一些,所以我们要再开一个size数组来记录原本的size。

*不开long long见祖宗

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define maxn 200001
using namespace std; struct edge{
int to,next; long long dis;
edge(){}
edge(const int &_to,const long long &_dis,const int &_next){ to=_to,dis=_dis,next=_next; }
}e[maxn<<1];
int head[maxn],k; int fa[maxn][20],size[maxn],size2[maxn],sum[maxn],maxdep;
int n;
long long m,dis[maxn][20]; inline long long read(){
register long long x(0),f(1); register char c(getchar());
while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
inline void add(const int &u,const int &v,const long long &w){ e[k]=edge(v,w,head[u]),head[u]=k++; } void dfs(int u){
size[u]=1;
for(register int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v==fa[u][0]) continue;
fa[v][0]=u,dis[v][0]=e[i].dis;
for(register int j=1;j<=maxdep;j++) fa[v][j]=fa[fa[v][j-1]][j-1],dis[v][j]=dis[v][j-1]+dis[fa[v][j-1]][j-1];
dfs(v),size[u]+=size[v];
}
} void dfs_getsum(int u){
for(register int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v==fa[u][0]) continue;
dfs_getsum(v);
long long len=0; int tmp=size[v],tmp2=size2[v];
for(register int j=maxdep;j>=0;j--) if(len+dis[v][j]<=m&&fa[v][j]) len+=dis[v][j],v=fa[v][j];
if(len+dis[v][0]>m&&fa[v][0]) sum[fa[v][0]]+=tmp,size[u]-=tmp2;
}
} void dfs_getans(int u){
for(register int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v==fa[u][0]) continue;
dfs_getans(v),sum[u]+=sum[v];
}
} int main(){
memset(head,-1,sizeof head);
n=read(),m=read();
for(register int i=2;i<=n;i++){
int v=read(); long long w=read();
add(i,v,w),add(v,i,w);
}
maxdep=(int)log(n)/log(2),dfs(1);
for(register int i=1;i<=n;i++) size2[i]=size[i]; dfs_getsum(1);
dfs_getans(1); for(register int i=1;i<=n;i++) printf("%d\n",size2[i]-sum[i]);
return 0;
}

[Usaco2012 Dec]Running Away From the Barn的更多相关文章

  1. BZOJ 3011: [Usaco2012 Dec]Running Away From the Barn( dfs序 + 主席树 )

    子树操作, dfs序即可.然后计算<=L就直接在可持久化线段树上查询 -------------------------------------------------------------- ...

  2. BZOJ_3011_[Usaco2012 Dec]Running Away From the Barn _可并堆

    BZOJ_3011_[Usaco2012 Dec]Running Away From the Barn _可并堆 Description 给出以1号点为根的一棵有根树,问每个点的子树中与它距离小于l的 ...

  3. 【BZOJ3011】[Usaco2012 Dec]Running Away From the Barn 可并堆

    [BZOJ3011][Usaco2012 Dec]Running Away From the Barn Description It's milking time at Farmer John's f ...

  4. [BZOJ3011][Usaco2012 Dec]Running Away From the Barn

    题意 给出一棵以1为根节点树,求每个节点的子树中到该节点距离<=l的节点的个数 题解 方法1:倍增+差分数组 首先可以很容易的转化问题,考虑每个节点对哪些节点有贡献 即每次对于一个节点,找到其第 ...

  5. bzoj3011 [Usaco2012 Dec]Running Away From the Barn 左偏树

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3011 题解 复习一下左偏树板子. 看完题目就知道是左偏树了. 结果这个板子还调了好久. 大概已 ...

  6. BZOJ_3012_[Usaco2012 Dec]First!_trie树+拓扑排序

    BZOJ_3012_[Usaco2012 Dec]First!_trie树+拓扑排序 题意: 给定n个总长不超过m的互不相同的字符串,现在你可以任意指定字符之间的大小关系.问有多少个串可能成为字典序最 ...

  7. 【BZOJ3012】[Usaco2012 Dec]First! Trie树+拓补排序

    [BZOJ3012][Usaco2012 Dec]First! Description Bessie has been playing with strings again. She found th ...

  8. [USACO 12DEC]Running Away From the Barn

    Description It's milking time at Farmer John's farm, but the cows have all run away! Farmer John nee ...

  9. USACO Running Away From the Barn /// 可并堆 左偏树维护大顶堆

    题目大意: 给出以1号点为根的一棵有根树,问每个点的子树中与它距离小于等于m的点有多少个 左偏树 https://blog.csdn.net/pengwill97/article/details/82 ...

随机推荐

  1. Idea中Web项目Jsp文件找不到类解决方法

    在src下创建package,java代码放到包中,编译时才能在WEB-INFO的classes文件夹中生成可识别的class文件 https://blog.csdn.net/youwanname/a ...

  2. css做keylogger

    下载keylogger:https://github.com/maxchehab/css-keylogging 参考讲解:https://blog.csdn.net/weixin_34138139/a ...

  3. C++libcurl的使用

    一.libcurl描述: 在curl的官方网站 **http://curl.haxx.se/download.html** 提供编译好libcurl包,  最后写一个demod工程,演示下libcur ...

  4. java基础:进制详细介绍,进制快速转换,二维数组详解,循环嵌套应用,杨辉三角实现正倒直角正倒等腰三角,附练习案列

    1.Debug模式 1.1 什么是Debug模式 是供程序员使用的程序调试工具,它可以用于查看程序的执行流程,也可以用于追踪程序执行过程来调试程序. 1.2 Debug介绍与操作流程 如何加断点 选择 ...

  5. IDEA使用SVN上传项目

    文章最后附上svn服务器和客户端下载地址 一.IDEA集成SVN 二.查看SVN仓库 调出svn视图: 连接svn服务器: 连接后效果如下: 忽略上传文件 忽略文件如下:可以选择按规则匹配 .idea ...

  6. java中游标

    package YouBiao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.Resu ...

  7. hadoop伪分布式平台组件搭建

    第一部分:系统基础配置 系统基础配置中主完成了安装大数据环境之前的基础配置,如防火墙配置和安装MySQL.JDK安装等 第一步:关闭防火墙 Hadoop与其他组件的服务需要通过端口进行通信,防火墙的存 ...

  8. [剑指 Offer 18. 删除链表的节点]

    [剑指 Offer 18. 删除链表的节点] 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点. 返回删除后的链表的头节点. 注意:此题对比原题有改动 示例 1: 输入: head ...

  9. sql操作数据库(2)--->DQL、数据库备份和还原

    查询 查询表中的所有的行和列的数据 ​ select * from 表名; ​ select * from student; 查询指定列的数据:如果有多个列,中间用逗号隔开. select 列名1,列 ...

  10. Java并发包源码学习系列:AbstractQueuedSynchronizer

    目录 本篇学习目标 AQS概述 AbstractOwnableSynchronizer 同步队列与Node节点 同步状态state 重要方法分析 独占式获取与释放同步状态 共享式获取与释放同步状态 A ...