BZOJ_3011_[Usaco2012 Dec]Running Away From the Barn _可并堆
BZOJ_3011_[Usaco2012 Dec]Running Away From the Barn _可并堆
Description
给出以1号点为根的一棵有根树,问每个点的子树中与它距离小于l的点有多少个。
Sample Input
4 5
1 4
2 3
1 5
1 4
2 3
1 5
Sample Output
3
2
1
1
做法不唯一,这里用来练习可并堆。
先求出每个点i 到根路径上的长度dis[i] ,对每个点建一个可并堆(大根)。
然后从下往上合并,如果当前dis[堆顶]−dis[x]>L 就弹出,记录每个节点最后剩下的点数即可。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 200050 typedef long long ll; ll val[N<<1],L,v[N]; int head[N],to[N<<1],nxt[N<<1],cnt,n,root[N],ls[N],rs[N],dis[N],siz[N]; inline void add( int u, int v,ll w) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w; } int merge( int x, int y) { if (!x) return y; if (!y) return x; if (v[x]<v[y]) swap(x,y); rs[x]=merge(rs[x],y); if (dis[ls[x]]<dis[rs[x]]) swap(ls[x],rs[x]); dis[x]=dis[rs[x]]+1; return x; } void dfs( int x, int y) { int i; siz[x]=1; root[x]=x; for (i=head[x];i;i=nxt[i]) { if (to[i]!=y) { v[to[i]]=v[x]+val[i]; dfs(to[i],x); siz[x]+=siz[to[i]]; root[x]=merge(root[x],root[to[i]]); } } while (v[root[x]]-v[x]>L) { siz[x]--; root[x]=merge(ls[root[x]],rs[root[x]]); } } int main() { dis[0]=-1; scanf ( "%d%lld" ,&n,&L); int i,x; ll y; for (i=2;i<=n;i++) { scanf ( "%d%lld" ,&x,&y); add(i,x,y); add(x,i,y); } dfs(1,0); for (i=1;i<=n;i++) { printf ( "%d\n" ,siz[i]); } } |
标签:
可并堆
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· Linux系列:如何调试 malloc 的底层源码
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· 对象命名为何需要避免'-er'和'-or'后缀
· JDK 24 发布,新特性解读!
· Java24你发任你发,我用Java8
· .NET Core奇技淫巧之WinForm使用Python.NET并打包
· C# 中比较实用的关键字,基础高频面试题!