首页 > 其他分享 >P1612 [yLOI2018] 树上的链

P1612 [yLOI2018] 树上的链

时间:2023-08-22 19:33:04浏览次数:36  
标签:二分 yLOI2018 top mid long 节点 100005 树上 P1612

因为自己太憨了,所以交了好几次都没过,谢谢审核大大!!!

思路

因为这是一棵树,所以每个节点只有一个父亲,那么选定一个结点,它到根节点的路径唯一。

所以第一个思路就是暴力,对于每一个节点,直接暴力向上枚举,找到第一个满足条件的节点,然后输出长度即可。

但是显然,第一种方法很容易 TLE,所以我们需要进一步优化。

我们随便给出一棵树,选取一条链。以叶节点为例,那么找到的最长链的另一个端点应该在路径上。

那么我们很容易想到了二分,快速找到适合的节点。

但是如果二分后还是暴力把所有值加在一起的话显然还是会超时,所以我们又自然地想到了前缀和。

最后一个问题,我们该如何确定二分的范围呢?我们可以在深搜的时候用一个栈,每搜索到一个新节点,就加入栈,然后在栈中二分,当这个节点遍历完了,就出栈。

对了,需要注意的是,这道题需要开 long long

AC 代码

#include<bits/stdc++.h>
using namespace std;
struct node{long long w,c,fa;vector<long long>v;}a[100005];//因为不确定儿子个数,所以用vector储存
long long n,ans[100005],z[100005],top,l,r,mid;
void dfs(long long u)
{
	z[++top]=u;//入栈
	l=0,r=top;
   a[u].w+=a[a[u].fa].w;//前缀和
	while(l<=r)//二分
	{
		mid=l+r>>1;
		if(a[u].w-a[z[mid]].w>a[u].c) l=mid+1;
		else ans[u]=top-mid,r=mid-1;
	}
	for(long long i=0;i<a[u].v.size();i++) dfs(a[u].v[i]);//向下搜索
	--top;//出栈
}
int main()
{
	scanf("%lld",&n);
	for(long long i=2;i<=n;++i) scanf("%lld",&a[i].fa),a[a[i].fa].v.push_back(i);
	for(long long i=1;i<=n;++i) scanf("%lld",&a[i].w);
	for(long long i=1;i<=n;++i) scanf("%lld",&a[i].c);
	dfs(1);
	for(long long i=1;i<=n;++i) printf("%lld ",ans[i]);
	return 0;
}

标签:二分,yLOI2018,top,mid,long,节点,100005,树上,P1612
From: https://www.cnblogs.com/One-JuRuo/p/17649490.html

相关文章

  • 树上问题4题
    P1600首先肯定要用到LCA,先用DFS预处理每个节点的第\(2^k\)代祖先和每个节点的深度,倍增计算LCA即可。最直接的做法是模拟每个人跑步的过程,但这种方法的最差复杂度是\(O(nm)\),肯定会超。考虑优化模拟过程,将模拟玩家改为枚举观察员,计算有几名玩家会为观察员做贡献。对于观察......
  • visual studio2022中使被排除的文件重新恢复显示在项目文件树上
    项目中有个叫Shape.cs的文件,不小心被排除了。使用添加现有项重新加入的话,IDE会提示文件已被添加,需要重新覆盖吗?此时不管选yesorno,这个cs文件不会出现在项目文件树上。选择编辑项目可以看到把这条Item配置删掉,cs文件就会重新出现在项目文件树上......
  • 【树】树上动态规划
    目录引入树形dp树上递推先序遍历(关键词:到根)后序遍历(关键词:子树)求直径(树上最长路径)换根DP法树上背包链式前向星引入考虑这样一个问题(P1352没有上司的舞会):一棵树,每个节点\(i\)都有价值\(v_i\),对于每个子节点,不能和父节点同时选择,求最大价值和。令dp[x][0]为在x的子树中......
  • [数据结构]树上倍增
    树上倍增一、一点理解最近遇到几个关于树上倍增问题。本人太菜,有时候想不到用倍增,这里做个总结。树上倍增核心就是:\(f[u][j]\),含义是\(u\)向上跳\(2^j\)步到的位置,然后用\(f[u][j]=f[f[u][j-1]][j-1]\)进行转移。树上倍增常见应用就是:快速幂、线性(RMQ问题)、树(LCA问题)。那么......
  • 树上前缀和
    树上前缀和模板传送门#include<algorithm>#include<cstring>#include<iostream>usingnamespacestd;typedeflonglongLL;typedefpair<int,int>PII;inlineintread(){intx=0,f=1;chars=getchar();while(s<�......
  • 树上询问
    #include<bits/stdc++.h>usingnamespacestd;constintN=1e6+5;intn,cnt,m,hd[N],c[N],l[N],r[N],d[N],ans[N];vector<int>q[N];structNode{intto,nxt;}edge[N];voidadd(intu,intv){edge[++cnt].to=v;edge[cnt].nxt......
  • 树上问题记录
    记录一下这一类问题。T1P4211[LNOI2014]LCA每次给出\(l,r,x\),定义\(dep_u\)为\(u\)节点到根节点的距离+1,求$\sum_{i=l}^rdep(lca(i,z))$。\(n\)个节点,\(m\)次询问,其中\(n,m\leq5e4\)。题目很简洁,我们如果暴力求每一个lca,复杂度将是\(O(n^2\logn)......
  • 【W的AC企划 - 第六期】树上分治
    往期浏览树上分治点分治讲解每次选取树的重心进行递归分治,中阶算法,大部分模板不需要理解,但是每一题都需要对维护函数进行修改。复杂度\(\mathcalO(N\logN)\)。个人封装由于需要进行一定程度的修改,不符合结构体封装的原则,故没有使用结构体。introot=0,MaxTree=1e1......
  • 树上计数2
    [树上计数2](2534.树上计数2-AcWing题库)我们先考虑一般的问题,即序列上的问题。发现这题是HH的项链。然后我们考虑树上怎么转换成序列上。我们使用欧拉序(对于每个点,在进入和离开时各记录一次,类比dfs序)。对于点\(u\),令\(fi_u,ls_u\)表示进入/出去的时间戳。如图(样例)......
  • 树上数据结构
    树上问题树链剖分学习笔记重链剖分对树进行重链优先搜索,暴力求一条路径的复杂度为logn模板voidtree_build(intu,intfa){//重链优先搜索 siz[u]=1; f[u]=fa; hson[u]=0; for(auto&v:adj[u]){deep[v]=deep[u]+1; if(v==fa)continue; tree_build(v,u);......