[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 ...
随机推荐
- YouZack英语学习网站,英语四六级的福音
YouZack英文网站 YouZack英语网站是,杨中科大佬开发给各位有需要的人使用的一个英语学习网站: 网站分两个模块: 听力模块部分图 听力模块界面 听力模块使用说明界面 背单词模块部分图 背单词 ...
- Application Data in Docker 笔记
Application Data in Docker By default all files created inside a container are stored on a writable ...
- nodeJS中的事件机制
events模块是node的核心模块,几乎所有常用的node模块都继承了events模块,比如http.fs等.本文将详细介绍nodeJS中的事件机制 EventEmitter 多数 Node.js ...
- 用Python写个开心消消乐小游戏
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 提到开心消消乐这款小游戏,相信大家都不陌生,其曾在 2015 年获得过玩家最喜爱的移动单机游戏奖,受 ...
- mssql不存在便插入存在不执行操作
前言 参考:https://www.jb51.cc/mssql/76911.html 在mssql中,在记录不存在时插入记录,如果存在则不执行操作 数据库 相关语句 --创建表 CREATE TABL ...
- java代理(静态代理和jdk动态代理以及cglib代理)
版权声明:本文为Fighter168原创文章,未经允许不得转载. 目录(?)[+] 说到代理,脑袋中浮现一大堆代理相关的名词,代理模式,静态代理,jdk代理,cglib代理等等. 记忆特别深刻 ...
- Qt学习笔记-安装phonon模块
如果想要运行使用Qt中的phonon写的程序,需要满足一下条件:Qt基本库.Qt phonon库.phonon_backend(后端插件)和多媒体播放后台.下面以linux(Fedora 12)系统. ...
- 01 . Go之从零实现Web框架(类似Gin)
设计一个框架 大部分时候,我们需要实现一个 Web 应用,第一反应是应该使用哪个框架.不同的框架设计理念和提供的功能有很大的差别.比如 Python 语言的 django和flask,前者大而全,后者 ...
- MVC和WebApi路由机制比较
1.MVC使用的路由 在MVC中,默认路由机制是通过解析url路径来匹配Action.比如:/User/GetList,这个url就表示匹配User控制器下的GetList方法,这是MVC路由的默认解 ...
- Fragment学习
利用Fragment可以动态的加载页面,减少Activity的数量. 便于开发 类似与html中FragmentSet一样 嵌套在一起,使每个页面为独立的 代码如下: package com.exam ...