zoukankan      html  css  js  c++  java
  • 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

    Sample Output

    3
    2
    1
    1


    做法不唯一,这里用来练习可并堆。

    先求出每个点$i$ 到根路径上的长度$dis[i]$ ,对每个点建一个可并堆(大根)。

    然后从下往上合并,如果当前$dis[堆顶]-dis[x]>L$ 就弹出,记录每个节点最后剩下的点数即可。

    代码:

    #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
    ",siz[i]);	
    	}
    }
    
  • 相关阅读:
    Python爬虫爬取糗事百科段子内容
    Python 的安装与配置(Windows)
    接口测试(二)—HttpClient
    接口测试(一)
    第一篇 什么是软件测试
    Python数据分析与挖掘第一篇—基本介绍及环境搭建
    从零开始搭建简易的异步非阻塞web框架
    Python多线程补充—GIL
    Python并发之多进程
    Python并发之多线程
  • 原文地址:https://www.cnblogs.com/suika/p/8891343.html
Copyright © 2011-2022 走看看