2021牛客多校第一场 C——Cut the Tree

hackerrank题目解答 hackerrank上面的经典题目解答,自习看完可以复习算法。 立即下载

题目大意

给你一棵树,每个点都有一个权值,让你在所有点中选择一个点删除,使得剩下的子树的最长上升子序列长度最小

解题思路

首先如何求树上最长上升子序列

参考博客

如何删点

首先,我们任取一个点 p p p 考虑删除点 p p p 的结果,删除点 p p p 之后,我们只需要考虑 p p p 的子树的最长上升子序列长度,即为答案,同时我们记录一下是哪一棵子树的最长上升子序列最长,我们如果要删其他点的话,那要删去的点一定在这棵子树之中(因为你再删除了这棵子树上的点的其他点是没有意义的,并不会对答案造成贡献)。
然后,如何选取 p p p 显然,我们每次选取要删点的树的重心即可,不然出现一条单链的话复杂度不够。
这样我们的复杂度是 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)

#include <bits/stdc++.h>
#define ll long long
#define qc ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define fi first
#define se second
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
using namespace std;
const int MAXN = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int head[MAXN];
int val[MAXN];
int n;
int ans;
struct edge{
	int next, to, w;
}e[MAXN << 1];
int cnt;
void init(){
	for(int i = 0; i <= n; i++)
		head[i] = -1;
	cnt = 0;
}
void add(int u, int v, int w = 0){
	e[cnt].w = w;
	e[cnt].to = v;
	e[cnt].next = head[u];
	head[u] = cnt++;
};
int tot;
struct Tree{
	int l, r;
	int lis, lds;
}tree[MAXN * 600];
int rt[MAXN];
int sz[MAXN];
int root, maxPart;
int res;
int vis[MAXN];
void getrt(int S, int u, int f){
	sz[u] = 1;
	int maxx = 0;
	for(int i = head[u]; ~i; i = e[i].next){
		int v = e[i].to;
		if(vis[v] || f == v)
			continue;
		getrt(S, v, u);
		sz[u] += sz[v];
		maxx = max(maxx, sz[v]);
	}
	maxx = max(maxx, S - sz[u]);
	if(maxx < maxPart){
		maxPart = maxx;
		root = u;
	}
}
int build(){
	tot++;
	tree[tot].l = tree[tot].r = tree[tot].lis = tree[tot].lds = 0;
	return tot;
}
void update(int &p, int l, int r, int pos, int vlis, int vlds){
	if(p == 0)
		p = build();
	tree[p].lis = max(tree[p].lis, vlis);
	tree[p].lds = max(tree[p].lds, vlds);
	if(l == r)
		return ;
	int m = (l + r) >> 1;
	if(pos <= m)
		update(tree[p].l, l, m, pos, vlis, vlds);
	else
		update(tree[p].r, m+1, r, pos, vlis, vlds);
}
int merge(int p, int q){
	if(!p || !q)
		return p + q;
	tree[p].lis = max(tree[p].lis, tree[q].lis);
	tree[p].lds = max(tree[p].lds, tree[q].lds);
	// 最大上升子序列长度
	res = max(res, max(tree[tree[p].l].lis + tree[tree[q].r].lds, 
		tree[tree[p].r].lds + tree[tree[q].l].lis));
	tree[p].l = merge(tree[p].l, tree[q].l);
	tree[p].r = merge(tree[p].r, tree[q].r);
	return p;
}
PII query(int p, int l, int r, int L, int R){ // L R 询问
	if(!p || l > r)
		return {0, 0};
	if(L <= l && r <= R)
		return {tree[p].lis, tree[p].lds};
	int m = (l + r) >> 1;
	PII ret = {-inf, -inf};
	PII tr, tl;
	if(L <= m)
		tl = query(tree[p].l, l, m, L, R);
	if(m < R)
		tr = query(tree[p].r, m+1, r, L, R);
	ret.fi = max(tl.fi, tr.fi);
	ret.se = max(tl.se, tr.se);
	return ret;
}
void dfs(int u, int f){
	rt[u] = 0;
	for(int i = head[u]; ~i; i = e[i].next){
		int v = e[i].to;
		if(v == f)
			continue;
		dfs(v, u);
	}
	int nlis = 0, nlds = 0;
	for(int i = head[u]; ~i; i = e[i].next){
		int v = e[i].to;
		if(v == f)
			continue;
		int lis = query(rt[v], 1, n, 1, val[u]-1).fi;
		int lds = query(rt[v], 1, n, val[u]+1, n).se;
		rt[u] = merge(rt[u], rt[v]);
		res = max(res, lis + 1 + nlds);
		res = max(res, nlis + 1 + lds);
		nlis = max(nlis, lis);
		nlds = max(nlds, lds);
	}
	update(rt[u], 1, n, val[u], nlis + 1, nlds + 1);
}
void calc(int S, int u){
	maxPart = S;
	getrt(S, u, 0);
	vis[root] = 1;
	int maxx = 0, pos = -1;
	for(int i = head[root]; ~i; i = e[i].next){
		int v = e[i].to;
		res = 0;
		dfs(v, root);
		if(res > maxx){
			maxx = res;
			pos = v;
		}
	}
	ans = min(ans, maxx);
	if(pos == -1 || vis[pos])
		return ;
	calc(sz[pos], pos);
}
void solve(){
	cin >> n;
	init();
	for(int i = 1; i < n; i++){
		int u, v;
		cin >> u >> v;
		add(u, v);
		add(v, u);
	}
	for(int i = 1; i <= n; i++)
		cin >> val[i];
	ans = inf;
	calc(n, 1);
	cout << ans << endl;
}

int main()
{
	#ifdef ONLINE_JUDGE
    #else
       freopen("in.txt", "r", stdin);
       freopen("out.txt", "w", stdout);
    #endif
	qc;
    int T;
    // cin >> T;
    T = 1;
    while(T--){

        solve();
    }
	return 0;
}
【控制模块算法】控制理论的进修之路 系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言一、(经典)自动控制理论【本科阶段】二、现代控制理论【本科阶段】三、最优控制理论【硕士阶段】总结 前言 认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长! 本文先对对控制理论的理解做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章 提示:以下是本篇文章正文内容 一、(经典)自动控制理论【本科阶段】 一般控制工程、自动化相关的考研专业课就是自动 阅读详情

相关推荐

YOLOv8魔改网络后训练全零?别慌,关掉AMP混合精度训练试试

本文探讨了YOLOv8魔改网络后训练出现全零指标的问题,指出AMP混合精度训练与自定义网络结构的不兼容性。通过分析梯度消失现象和AMP工作原理,提供了关闭AMP、调整学习率等解决方案,并建议预防性开发实践以避免类似问题。

weixin_28338005的博客 321

【Codeforces - 1592C】Bakry and Partitioning

原题链接:Bakry and Partitioning 题意 给你一棵共n个节点的树,每个节点有对应的值,要求删除1~(k-1)条边使得所有连通块的异或和相同。 分析 对于树上异或和问题,通用做法是先处理出每个节点与其子树所有节点的异或和,一遍dfs便可获得。 一棵树删除一条边后,便会产生两个连通块,也可称为子树,【原根节点所在子树的异或和】需要异或上 【另一子树的异或和】,因为一个数连续异或相同的数两次还是原来的数。 由此可见,当只删除一条边时,要保证两个新的连通块异或和相同,当且仅当原来的树的异或和等于

m0_55470059的博客 543

Miniconda3迁移(附图详细过程)

服务器上目录占满,想要将conda迁移到其他目录下的操作方法,详细教程。

2301_77554343的博客 6942

割点详解

定义:在一个无向图中,如果去掉一个点和它所连出去的的所有边,使得剩下的点不联通(即分成一个以上的强连通分量)时,这个点被称为关节点。题目:来看一道裸题:有n(1≤n≤10^6)个点,m(1≤m≤5*10^6)条边,现在让你求图中所有的关节点。思路1:枚举+dfs枚举割掉那些点,再跑深搜看看剩下的点是否连通即可。时间复杂度:O(n(n+m))代码就不贴了(人人都会打)。思路2:割点模板(类似于强连通...

zsyz_ZZY的博客 5682

5.4 磁悬浮轴承控制系统仿真:在MATLAB/Simulink中搭建包含功放、传感器模型的闭环系统模型,进行稳定性与动态性能仿真

磁悬浮轴承控制系统仿真方法 摘要:磁悬浮轴承控制系统仿真需建立包含转子动力学、传感器、控制器、功率放大器和电磁执行器的高保真非线性模型。通过MATLAB/Simulink搭建闭环系统,重点建模传感器带宽限制与噪声、功放饱和特性以及电磁力非线性。仿真分析包括时域阶跃响应、扰动抑制测试,频域稳定性分析(伯德图、奈奎斯特图),以及参数摄动下的鲁棒性验证。关键要验证控制算法在非线性因素影响下的稳定性和动态性能,为实际系统实现提供可靠依据。仿真中需特别注意物理量单位一致性和数字控制离散化效应。

技术工作者 1107

全志 T527_Android13 编译 [ 避坑必看 ]

Swap 概念: Linux中Swap(即:交换分区),类似于Windows的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。它的功能就是在内存不够的情况下,操作系统先把内存中暂时不用的数据,存到硬盘的交换空间,腾出内存来让别的程序运行。当输入编译命令make -j16 的时候,会有如下提示,这是官方建议通过减少编译线程来解决编译时消耗内存过大的问题。Android 13 系统的编译流程,编译一共分为两部分:内核编译与 Android 编译。

公众号:嵌入式分享 2111

LeetCode 刷题系列 -- 1110. 删点成林

中出现,我们就把该节点从树上删去,最后得到一个森林(一些不相交的树构成的集合)。to_delete 包含一些从 1 到 1000、各不相同的值。每个节点都有一个介于 1 到 1000 之间的值,且各不相同。返回森林中的每棵树。你可以按任意顺序组织答案。,树上每个节点都有一个不同的值。树中的节点数最大为 1000。

qq_33775774的博客 737

学习STM32的CAN总线通信

在配置时,确保您启用了CAN总线功能。CAN节点是CAN总线上的一个设备,每个节点都有唯一的标识符。在CAN总线中,有两种类型的节点:CAN控制器和CAN外设。步骤2:配置CAN总线 在STM32CubeMX中,选择CAN总线模块并进行必要的配置。在CAN总线中,有两个重要的概念:CAN节点和CAN帧。步骤5:测试CAN总线通信 在成功编译和烧录代码后,您可以使用串口调试助手或其他CAN总线工具来测试CAN总线通信。步骤3:编写CAN总线通信代码 在项目的主代码文件中,我们将编写CAN总线通信的示例代码。

2401_85258012的博客 496

【HackerRank】Cut the tree

题目链接:Cut the tree 题解:题目要求求一条边,去掉这条边后得到的两棵树的节点和差的绝对值最小。 暴力求解会超时。 如果我们可以求出以每个节点为根的子树的节点之和,那么当我们去掉一条边(a,b)的时候,其中的一棵树必是以a或者b为根的子树,那么我们就可以知道生成的两棵树的节点之和了。所以,当我们得到以每个节点为根的子树节点和这个信息后(把这个信息存储在TreeNode的value...

weixin_30715523的博客 291

【信息系统项目管理师】第1章:信息化发展 考点梳理

本文主要详细梳理高项:信息化、新型基础设施建设、两化融合、数字中国、数字化转型与元宇宙等内容。

数据知道的博客 8576

【TC397第23篇】深度解析TC397 EB MCAL开发系列:UART配置与POLL模式数据交互

通过本文,我们深度解析了TC397 EB MCAL开发系列中UART配置的POLL模式下的数据交互。从技术要点的介绍到实际案例的演示,希望读者能够更好地理解UART在POLL模式下的配置与应用。这不仅是对嵌入式系统开发的一次深刻探索,更是为项目提供了一种高效通信的解决方案。在未来的文章中,我们将继续深入研究嵌入式系统开发的各个方面,为广大开发者提供更多实用的技术知识。敬请期待,一同迎接嵌入式技术的新篇章!

一直在水些技术小文 470

树形DP YBTOJ专项

被自己之前的代码丑哭了:(

fervency(洛谷id)的博客 361

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

线段树合并与分裂维护树上最长上升子序列 + 点分治删点 ---- 2021 牛客多校第一场 C - Cut the tree(详解)

题目大意: 给你一个树,树上每个点都有一个权值valnodeval_{node}valnode​,路径(u,v)(u,v)(u,v) 上所有点按顺序有序序列,令f(u,v)f(u,v)f(u,v)是这个序列的最长上升子序列的长度,设GGG是max(f(u,v))∣(u,v)是可达的max(f(u,v))|(u,v)是可达的max(f(u,v))∣(u,v)是可达的 现在叫你删除一个点vvv使得GGG最小 解题思路: 思路1:求解树最长上升子序列怎么求? 首先我们先假设是对一个有根的树求 对于一个dp[i

weixin_45630722的博客 333

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

2021牛客多校1——C:Cut the Tree(点分治,数的重心,树上最长上升子序列,动态权值线段树)

题面 题意: 给一个带点权的树,你可以删去树上一个点,最小化所有子树最长上升子序列的长度最大值 。N <= 100000 前置知识: 树的重心 点分治 权值线段树 动态开点 参考资料 树分治 - OI Wiki (oi-wiki.org) 『权值动态开点线段树』『线段树合并算法』简单理解_Ronaldo7_ZYB的博客-优快云博客_权值线段树合并 【AgOHの算法胡扯】点分治_哔哩哔哩_bilibili 思路: 要最小化所有子树的最长上升子序列的最大值,我们可以每次取这棵带权树的重心.

kunyuwan的博客 779

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

2021年暑假牛客多校第一场 | 总结

比赛链接:https://ac.nowcoder.com/acm/contest/11166 菜狗,大佬勿喷 简单题解A. Alice and Bob | 博弈论 | sg函数B. Ball Dropping | 简单计算几何C. Cut the Tree | 线段树 (未补)D. Determine the Photo Position | 签到E. Escape along Water Pipe | BFS和DFSF. Find 3-friendly Integers | 抽屉原理G. Game o.

mldl_的博客 687

2021牛客暑期多校训练营1

2021牛客暑期多校训练营1 2021牛客暑期多校训练营1 G 首先需要了解的是题目需要我们输出的是绝对值的差值,在abs运算中一定是大数去减去小数的,所以题目是有一个隐藏的无限制的次数的操作,就是交换a,b序列中相同位置的值。所以为了方便理解可以将a序列看做大数序列,b序列看作小数序列。 现在我们进行k次操作,使得答案的值变大。那么在什么时候答案的值会变大呢? 如果b序列中的某个数bi,比a序列中的某个数aj要大的话,那么显然将bi和aj互换的话,答案是会变大的。因为是2个较大的数在相减,和2个较小的

rickwang000的博客 276

题解 | Go on Strike!-2019牛客暑期多校训练营第二场C题

**题目来源于牛客竞赛:**https://ac.nowcoder.com/acm/contest/discuss 题目描述: There are N cities in Eddy’s neverland. There are some flights to connect some pair of cities. Except flight, there’s no any other way t...

lastbye的博客 517

[学习笔记] Link-Cut-Tree

终于学了 link-cut-tree\text{link-cut-tree}link-cut-tree ,我是看FlashHu 的博客学的。 概念简述 lct\text{lct}lct 的思想主要是把连向某一个儿子的边划分为实边,其它的边划分成虚边。 区别在于虚实是可以动态变化的,因此要使用更高级、更灵活的Splay来维护每一条由若干实边连接而成的实链。 lct\text{lct}lct的主要性质...

C202044zxy的博客 337

LCT(Link-Cut-Tree)学习笔记

Link-Cut-Tree

Unlimited Code Works 771

【学习笔记】动态树(Link-Cut Tree)

没准可以考虑线段树分治。

七代目鸽影 874

link-cut-tree

注意: ①左父亲右儿子!!每棵splay中的点左子树的深度都比当前点小,右节点的深度都比当前节点的深度大。 题: xsy1173(YES) 一个朴素的想法就是暴力加入区间中的每一条边。 对于加入的一条边,它可能将两个联通块连起来,也可能没有任何贡献。 定义一个c[],c[x]=1就是有贡献,c[x]=0为没有贡献。 对于没有贡献的情况我们将链中编号最小的边删去,将其在c[]中变为0,强

fighting 915

XCPC算法模板高级数据结构:Link-Cut Tree、可持久化数据结构实战应用

在XCPC/ICPC/CCPC等算法竞赛中,高级数据结构是解决复杂问题的关键。本文将深入解析XCPC算法模板中的Link-Cut Tree(动态树)和可持久化数据结构,帮助你掌握这些强大工具的实战应用技巧。 ## 一、Link-Cut Tree:动态树问题的终极解决方案 Link-Cut Tree(简称LCT)是一种能够高效处理动态树问题的数据结构,它可以在O(log n)时间内完成树的链接、

gitblog_00207的博客 464

动态树 LCT(Link-Cut-Tree)--入门教程

什么是LCT(Link-Cut-Tree)根据杨哲先生的论文(QTREE),可以得知,动态树问题是一类问题的统称,而解决这种问题最常用到的数据结构就是LCT(Link-Cut-Tree)。LCT的大体思想类似于树链剖分中的轻重链剖分,轻重链剖分是处理出重链来,由于重链的定义和树链剖分是处理静态树所限,重链不会变化,变化的只是重链上的边或点的权值。由于这个性质,我们用线段树来维护树链剖分中的重链,但是

yashem66 4657

Link-Cut Tree(知识总结+板子整理)

思路来源 https://www.luogu.com.cn/blog/flashblog/solution-p3690 https://www.cnblogs.com/19992147orz/p/8206693.html https://www.cnblogs.com/candy99/p/6271344.html 前置知识 splay:真正理解rotate、会区间翻转 树链剖分:轻重链的概念 心得 杭电多校LCT的题,被120队过,不学新知识不行了,哎…… 强推第一篇洛谷题解,有图可供食用

小衣同学的博客 648

Cut the Tree

Atul 对图论感兴趣,最近他正在学习树形结构。他发现在一颗树 T 上移除一条边会生成两个分开的树:T1 和 T2。 树 T 的每个顶点被赋予了一个正整数。你的任务是移除一条边使得 *Tree_diff* 最小化, *Tree_diff* 的定义如下: F(T) = 树T上各顶点的数值之和。 Tree_diff(T) = abs(F(T1) - F(T2)) 输入格式 第一行包含一...

Do not mess it up 619

8.13 18级杭电多校第八场

文章目录比赛过程题解题意解法代码 比赛过程    题解 题意    解法    代码

weixin_44208681的博客 259
上一篇: 树上最长上升子序列——线段树合并
下一篇: 2021牛客多校第一场 E——Escape along Water Pipe
Linda_yezi_coder
博客等级 码龄7年 20粉丝 88原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值