树链刨分——将树转为链

简单

树链剖分

传送门
题意:给定一颗树,给定树上所有点的点权,有 4 种操作,①:给 u 到 v 的链每个点都 + k;②:求 u 到 v 的点权和;③:对 u 的所有子树的点 + k;④:求 u 所有子树的点权和
做法:树链剖分是根据重儿子的重链来将树转化成一条链,可以保证将树上的一条链分割成最多log(n)不连续区间,然后就可以对区间进行操作,即转化成线段树或者树状数组等。是非常重要的算法,如果对区间的处理是log的,那么对任意一条链的操作是 log(n)2
性质1:以任意节点为根节点的子树必定是一段连续的区间

中等

较难

Static Query on Tree

传送门
题意:给定一棵树,树中所有边都是单向边,但是保证所有点都指向根节点1,多组输入,每组里面首先会构造出树,其次在有 q 次询问,每次询问给定三个集合a,b,c,问有多少个点 x 符合以下规则:
①:a 和 b 中至少各有一个点能到达 x
②:x 能到达 c 中最少一个点
数据范围要求每次询问的时间复杂度是 (a + b + c) * log(a + b + c) 2
做法: 第一点:题目明确要求是单向边,看似很多树的性质都不能用,但是题目保证所有点都能到达 1,所以把 1 作为根节点建树,我们会发现所有边都是向上的,所以 x 的位置可以确定了,x 的位置符合下列两条:
①:a 集合所有点向上延伸到根节点的路径中所有点集 和 b 集合所有点向上延伸到根节点的路径中所有点集交集。说成人话就是,a 中所有点和根节点的链都染色成 A, 中所有点和根节点的链都染色成 B,那么 x 必然是两种颜色都有的点
②:因为 x 要到达 c 中节点,所以 x 也要在 c 中节点的子树下。人话就是对 c 中所有节点的子树染色成C,那么 x 肯定是在有颜色 C 的点
总结一下:x 要同时符合上述两点,即 x 的颜色包含三种:A,B,C
当我们把上面两条搞出来的时候就说明,这题很明显就是树链剖分了,分出来后跑线段树染色即可。
那么题意现在可以简化成:先给出要染成颜色 A 的多个区间,再给出要染成 B 的多个区间,最后给出要染成 C 的多个区间,问整棵树种有多少三种颜色都有的点
这题的难点就在线段树上,写的时候换了好几种方案都不对,下面解释一下我遇到的几种错解:
第一种:
因为染色是有顺序的,所以线段树中维护一个 sum,在染 A 颜色时,sum 就是当前区间被染 A 的点数,染 B 时,sum 通过取 min 变成区间内被染 A 和 B 的点数,染 C 时同理。看似好像有道理,但实际上大错特错,首先如果一个区间被 A 染但是没有被 B 染,那么这个区间的 sum 是无法取 min 变成 0 的,因为我根本没有递归到这个区间的,所以在 pushup 上去时就会出现有一个儿子 sum 没更新但是还是作为正确答案传上去。
第二种:
吸收上一个做法的经验,我们 sum 的含义改为既被染 A 也被染 B 的点数,如果把 C 染进去同时 sum 取 min 更新,显然和上一个错在同一个地方
第三种:
我们直接定义 sum 是被三种颜色都染的点数,在染 C 时,我们会发现如果我们不递归下去我们就无法找到当前区间内被 A 和 B 都染的点,如果单纯记录 A 的数量和 B 的数量,两种取 min 求 C 的数量,那更是错的离谱,左子树全被染 A,右儿子全部染 B,A 数量和 B 数量取 min 不是 0。
在前三种错误做法种取了折中,找到一种正确做法,比较类似与第二种,但是染 C 时不取 min 更新 sum,而是直接将 sum 加入答案。为了去重,我们需要对 C 内节点按深度排序,同时染 C 时判断是否被染过即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
决策模型是一种常用的算法,可以用于鸢尾花类。剪枝是为了解决过拟合问题而进行的一种策略。在剪枝之前和剪枝之后,我们可以通过交叉验证来评估模型的正确率。 下面是一个示例代码,演示了使用决策模型对鸢尾花数据集进行类,并比较了剪枝前后的正确率: ```python from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import accuracy_score # 加载鸢尾花数据集 iris = load_iris() X = iris.data y = iris.target # 划训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 构造决策模型(剪枝前) clf_before_pruning = DecisionTreeClassifier() clf_before_pruning.fit(X_train, y_train) # 预测并计算剪枝前的正确率 y_pred_before_pruning = clf_before_pruning.predict(X_test) accuracy_before_pruning = accuracy_score(y_test, y_pred_before_pruning) # 构造决策模型(剪枝后) clf_after_pruning = DecisionTreeClassifier(ccp_alpha=0.1) # ccp_alpha为剪枝参数 clf_after_pruning.fit(X_train, y_train) # 预测并计算剪枝后的正确率 y_pred_after_pruning = clf_after_pruning.predict(X_test) accuracy_after_pruning = accuracy_score(y_test, y_pred_after_pruning) print("剪枝前的正确率:", accuracy_before_pruning) print("剪枝后的正确率:", accuracy_after_pruning) ``` 运行以上代码,可以得到剪枝前和剪枝后的正确率。剪枝后的正确率可能会有所下降,但剪枝可以减少过拟合问题,提高模型的泛化能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值