[Usaco2012 Dec]Running Away From the Barn
题目描述
给出以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的更多相关文章
- BZOJ 3011: [Usaco2012 Dec]Running Away From the Barn( dfs序 + 主席树 )
子树操作, dfs序即可.然后计算<=L就直接在可持久化线段树上查询 -------------------------------------------------------------- ...
- BZOJ_3011_[Usaco2012 Dec]Running Away From the Barn _可并堆
BZOJ_3011_[Usaco2012 Dec]Running Away From the Barn _可并堆 Description 给出以1号点为根的一棵有根树,问每个点的子树中与它距离小于l的 ...
- 【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 ...
- [BZOJ3011][Usaco2012 Dec]Running Away From the Barn
题意 给出一棵以1为根节点树,求每个节点的子树中到该节点距离<=l的节点的个数 题解 方法1:倍增+差分数组 首先可以很容易的转化问题,考虑每个节点对哪些节点有贡献 即每次对于一个节点,找到其第 ...
- bzoj3011 [Usaco2012 Dec]Running Away From the Barn 左偏树
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3011 题解 复习一下左偏树板子. 看完题目就知道是左偏树了. 结果这个板子还调了好久. 大概已 ...
- BZOJ_3012_[Usaco2012 Dec]First!_trie树+拓扑排序
BZOJ_3012_[Usaco2012 Dec]First!_trie树+拓扑排序 题意: 给定n个总长不超过m的互不相同的字符串,现在你可以任意指定字符之间的大小关系.问有多少个串可能成为字典序最 ...
- 【BZOJ3012】[Usaco2012 Dec]First! Trie树+拓补排序
[BZOJ3012][Usaco2012 Dec]First! Description Bessie has been playing with strings again. She found th ...
- [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 ...
- USACO Running Away From the Barn /// 可并堆 左偏树维护大顶堆
题目大意: 给出以1号点为根的一棵有根树,问每个点的子树中与它距离小于等于m的点有多少个 左偏树 https://blog.csdn.net/pengwill97/article/details/82 ...
随机推荐
- 多任务-python实现-进程,协程,线程总结(2.1.16)
@ 目录 1.类比 2.总结 关于作者 1.类比 一个生产玩具的工厂: 一个生产线成为一个进程,一个生产线有多个工人,所以工人为线程 单进程-多线程:一条生产线,多个工人 多进程-多线程:多条生产线, ...
- Arduino PROGMEM 从程序空间读取float值的方法
方法: 使用avr-libc提供的宏定义: #define pgm_read_float_near(address_short) __LPM_float((uint16_t)(address_shor ...
- Unity使用小剧场—创建的按钮On Click()只有MonoScript怎么办
前言: 在游戏开发过程中遇到了一些小问题,以后都放到小剧场里,今天介绍怎么给按钮赋予方法并解决标题所述问题. 步骤: 1. 不管怎么说,先新建一个按钮 右键场景-[UI]-[Button] 这里会自动 ...
- .NET Core AWS S3云存储
前言 最近有需要用到AWS S3云存储上传附件,这里对利用.NET或.NET Core在调用SDK APi需要注意的一点小问题做个记录,或许能对后续有用到的童鞋提供一点帮助 AWS S3云存储 官方已 ...
- CentOS7下常用安装服务软件源码编译安装方式的介绍
简介:介绍源码编译安装软件包的管理 源码安装优点:编译安装过程,可以设定参数,指定安装目录,按照需求进行安装,指定安装的版本,灵活性比较大. 源码安装的缺点:需要对依赖包一个一个的进行安装,不敢随便升 ...
- mac 清理磁盘空间
128G mac真的用的很崩溃,发现系统占用80G ,肯定是有问题的,发现了是缓存的原因,删除后好多了,记录一下. 从管理里进入之后,从文稿中选择"文件浏览器"可以看到每一个文件夹 ...
- javap使用
在反编译前你当然需要先编译这个类了进入当前目录下:javac -g SynchronizedTest.java(使用-g参数是因为要得到下面javap -l时的输出需要使用此选项) 编译完成后,我们在 ...
- Spring Boot 有哪些优点?
a.减少开发,测试时间和努力. b.使用 JavaConfig 有助于避免使用 XML. c.避免大量的 Maven 导入和各种版本冲突. d.通过提供默认值快速开始开发.没有单独的 Web 服务器需 ...
- String 类的常用方法都有那些?
1.indexOf():返回指定字符的索引. 2.charAt():返回指定索引处的字符. 3.replace():字符串替换. 4.trim():去除字符串两端空白. 5.split():分割字符串 ...
- JAVA编程能力提升学习图
阿里大神毕玄整理的关于进阶JAVA的学习体系,知道下...