首页 > 其他分享 >[题解]NOIP2018模拟赛 plutotree

[题解]NOIP2018模拟赛 plutotree

时间:2024-10-16 20:59:32浏览次数:1  
标签:maxx leaf int 题解 点权 NOIP2018 fa plutotree 节点

题目描述

给定一棵有\(n\)个节点的树,根节点为\(1\),节点\(i\)有权值\(w[i]\)。这棵树非常奇怪,它的每个叶子结点都有一条连向根节点的权值为\(0\)的边。给定\(q\)次询问,每次给定\(u,v\),请计算出一条\(u\)到\(v\)的路径(每条边最多经过\(1\)次),最小化该路径上的点权之和,并在其基础上最大化该路径上的最大点权。

输入的第\(1\)行\(2\)个整数表示\(n\)和\(q\);第\(2\)行有\(n-1\)个正整数,第\(i\)个正整数表示节点\(i+1\)的父节点是\(i\);第\(3\)行\(n\)个整数,第\(i\)个整数表示\(w[i]\);接下来\(q\)行,每行\(2\)个整数\(u,v\),表示一次查询。

输出\(1\)行\(2\)个整数,表示点权和与最大点权。

  • \(1\le n,q\le 10^5\)
  • \(0\le w[i]\le 10^9\)。
Sample #1

Input:

5 1
1 2 3 4
413 127 263 869 960

Output:

1373 960

解题思路

下面所说的“树上”均之未添加特殊边的树上,“距离”均指路径的点权和。

我们分类讨论,答案显然可以分为下面\(4\)种:

  • \(u\)和\(v\)经树上的最短路径,在\(lca(u,v)\)处相遇。
  • \(u\)从最近的叶子结点到根节点,\(v\)通过树上路径到根节点,在根节点相遇。
  • \(u\)通过树上路径到根节点,\(v\)从最近的叶子结点到根节点,在根节点相遇。
  • \(u,v\)都通过最近的叶子节点到根节点,在根节点相遇。

虽然上面的部分情况可能走重复边,但这样它就一定不是最优答案了,所以不影响。

所以我们要处理的是:

  • \(u\)到\(v\)在树上的距离和路径上最大点权。
  • \(u\)到最近叶子节点的距离和路径上最大点权。

前者可以直接用倍增求LCA来实现。而后者可以通过\(2\)次dfs来实现:

  • 用结构体变量leaf[u]来表示\(u\)到最近叶子节点的信息(距离\(x\)和最大点权\(y\))。
  • 对于叶子结点,初始令leaf[u]={w[u],w[u]}
    对于其他节点,初始令leaf[u]={+inf,w[u]}
  • 第\(1\)次dfs,自下而上更新\(leaf\),即\(leaf[u]\)仅考虑了\(u\)子树中的叶子结点。
    搜索完子节点\(i\)后,leaf[u]=upd(leaf[u],{leaf[i].x+w[u],leaf[i].y})
  • 第\(2\)次dfs,自上而下再更新一次\(leaf\),完成\(leaf\)的计算。
    搜索子节点\(i\)之前,leaf[i]=upd(leaf[i],{leaf[u].x+w[i],leaf[u].y})
  • 其中upd()是用于更新答案的,根据定义执行即可:\(x\)不同取最小,\(x\)相同\(y\)取最大。

这样就完成了,对于每次查询更新\(4\)次答案即可,答案和LCA函数也用相同的结构体类型来存储即可,具体见代码。

时间复杂度\(O((n+q)\log n)\)。

Code

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 100010
#define Q 100010
using namespace std;
struct res{int x,y;}leaf[N];
void update(res& a,res b){
	if(b.x<a.x) a=b;
	else if(b.y==a.y) a.y=max(a.y,b.y);
}
int n,q,w[N],dep[N],fa[N][20],maxx[N][20],d[N];
vector<int> G[N];
void dfs1(int u){//计算d,dep,并自下而上更新leaf 
	dep[u]=dep[fa[u][0]]+1;
	if(G[u].empty()) leaf[u]={w[u],w[u]};
	else leaf[u]={LLONG_MAX,w[u]};
	for(int i:G[u]){
		d[i]+=d[u];
		dfs1(i);
		update(leaf[u],{leaf[i].x+w[u],leaf[i].y});
	}
}
void dfs2(int u){//自上而下再更新一次leaf,完成leaf的计算 
	for(int i:G[u]){
		update(leaf[i],{leaf[u].x+w[i],leaf[u].y});
		dfs2(i);
	}
}
res LCA(int u,int v){//返回{距离,最大点权}
	if(dep[u]<dep[v]) swap(u,v);
	int tmax=max(w[u],w[v]),tdis=d[u]+d[v];
	for(int i=19;i>=0;i--)
		if(dep[fa[u][i]]>=dep[v])
			tmax=max(tmax,maxx[u][i]),
			u=fa[u][i];
	if(u==v) return {tdis-d[u]-d[fa[u][0]],tmax};
	for(int i=19;i>=0;i--)
		if(fa[u][i]!=fa[v][i])
			tmax=max(tmax,max(maxx[u][i],maxx[v][i])),
			u=fa[u][i],v=fa[v][i];
	int lca=fa[u][0];
	tmax=max(tmax,max(maxx[u][1],maxx[v][1]));
	return {tdis-d[lca]-d[fa[lca][0]],tmax};
}
signed main(){
	cin>>n>>q;
	for(int i=2;i<=n;i++){
		cin>>fa[i][0];
		G[fa[i][0]].emplace_back(i);
	}
	for(int i=1;i<=n;i++){
		cin>>w[i];
		d[i]=maxx[i][0]=w[i];
	}
	dfs1(1),dfs2(1);
	for(int j=1;j<=19;j++){
		for(int i=1;i<=n;i++){
			fa[i][j]=fa[fa[i][j-1]][j-1];
			maxx[i][j]=max(maxx[i][j-1],maxx[fa[i][j-1]][j-1]);
		}
	}
	while(q--){
		int u,v;
		cin>>u>>v;
		res ans=LCA(u,v);//1. u,v在LCA相遇
		update(ans,{leaf[u].x+d[v],max(leaf[u].y,maxx[v][19])});//2. u去叶子v去根
		update(ans,{leaf[v].x+d[u],max(leaf[v].y,maxx[u][19])});//3. v去叶子u去根
		update(ans,{leaf[u].x+leaf[v].x+w[1],max(max(leaf[u].y,leaf[v].y),w[1])});//4. u,v都去叶子
		cout<<ans.x<<" "<<ans.y<<"\n";
	}
	return 0;
}

变量含义说明:

  • \(d[u]\):\(u\)到根节点的距离。
  • \(maxx[u][i]\):\(u\)向上\(2^i\)个节点(包括\(u\))的最大权值。

标签:maxx,leaf,int,题解,点权,NOIP2018,fa,plutotree,节点
From: https://www.cnblogs.com/Sinktank/p/18470861

相关文章

  • P10353 [PA2024] Grupa permutacji 题解
    神秘!在这些排列生成的置换群\(G\)里,若\(\exists\pi\inG\)使得\(\pi_i=k,\pi_j=l\),则所有这些\((k,l)\)被同样数量的\(\pi\inG\)通过前述方法得出。证明:设\(\pi(i,j)=(k,l),\pi'(i,j)=(k',l')\)(意义前述),则\(\pi^{-1}\circ\pi'(k,l)=(k',l')......
  • [题解]P3952 [NOIP2017 提高组] 时间复杂度
    P3952[NOIP2017提高组]时间复杂度我们把循环的嵌套关系看做树形结构,梳理一下\(3\)种情况:直接跳过当前子树:\(x,y\in\mathbb{N}\),且\(x>y\)。\(x=\tt{"n"},y\in\mathbb{N}\)。不跳过,并在处理完所有子节点后追加\(n\)的时间复杂度:\(x\in\mathbb{N},y=\tt{"n"}\)。......
  • 【题解】[2023 合肥蜀山初中] 旅行(travel)
    题目传送门题目大意有一个\(n\)个点\(m\)条边的有向图组成的城市,每条边可以是骑行边或公共交通边,公共交通边只能走一条,边是从\(u_i\)到\(v_i\)的有向边,需要花费\(time_i\)的时间,求\(1\)到其他点的最短路径。思路分析有一个很巧妙的思路叫分层图,它的思路是因为只能......
  • Excel DLL丢失?Excel DLL文件下载指南及常见问题解决方案
    当您在使用MicrosoftExcel时遇到提示DLL文件丢失或损坏的情况,这可能会影响软件的正常运行。为了帮助您解决这一问题,本文提供了ExcelDLL文件的下载指南,并针对常见问题给出了解决方案。一、ExcelDLL文件下载指南确定缺失的DLL文件:首先,您需要确定是哪个DLL文件丢失或损坏......
  • 数据结构1系列题解前瞻
    A.线段树分裂算法:线段树、(平衡树?)板子题,不多做评价。但是开发空间很大,我的写法在洛谷题解上没找到,导致当时想贺题解没贺成。B.三元上升子序列算法:线段树、树状数组、分块、(CDQ分治?)二维偏序板子,开发空间极大,想怎么写就怎么写。C.STEP算法:线段树、分块线段树维护子区间信......
  • P1941 NOIP2014 提高组 飞扬的小鸟 题解
    P1941NOIP2014提高组飞扬的小鸟分析背包经典演变问题玩得挺花。设\(f[i][j]\)表示到达\((i,j)\)的时候的最小点击次数。题目中对于每一个\(i\)有两种处理:点击与不点击(重点:点击可以叠加)。所以,对于点击,我们可以像完全背包一样转移,而不点击就按照01背包转移。对于管......
  • [NOI2020] 美食家 题解
    属于是将矩阵快速幂的绝大部分技巧用到了极致的一道题。暴力部分首先我们先考虑一个普通DP。定义\(dp_{t,i}\)表示在时间为\(t\)时到达点\(i\)可以得到的愉悦值之和的最大值。显然有\((i,j)\inE\todp_{t+w,j}=\max(dp_{t,i}+c_j)\)。特判一下当前节点有美食节的情......
  • 洛谷 P5175 数列 题解
    纯纯数学题。看到\(n\le10^{18}\)不难想到矩乘,但是\(\log_210^{18}\approx60\),再加上\(T=30000\)的多测,运算量已经来到了\(1.8\times10^6\),所以我们最多有一个\(\sqrt[3]{\frac{1.5\times10^8}{6\times10^6}}\approx4\)的矩阵。\[\becausea_i=xa_{i-1}+ya_{......
  • Project Euler 588 题解
    这玩意好像甚至有递推式……不太懂(为什么是图片?cnblogs第一个公式没渲染成功)时间复杂度是\(O(4^{\degF}\logK)\)的。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintmaxn=100;intf[17][maxn],cur[10],al[4];intcalc(intK){ //cer......
  • 题解:[SNCPC2019] Pick Up
    ProblemLink[SNCPC2019]PickUp题意给出甲的坐标和速度,乙的坐标和速度,商场的坐标,可以让乙去接甲,求甲前往商场的最短用时。Solution分类讨论。思考乙是否要去接甲。这个很简单,令\(ans1\)为甲自己出发耗时,\(ans2\)为乙接甲耗时,两者取最小值即可。\(ans1\)很好算,那么\(......