声明
笔者最近意外的发现 笔者的个人网站 http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明。
郑重声明:这篇记录《【百度之星2014~复赛 解题报告~正解】The Query on the Tree》转载自 http://tiankonguse.com/的这条记录:http://tiankonguse.com/record/record.php?id=674
前言
昨天写了 The Query on the Tree 的解题报告,但是遗留下一个问题,不能算是完美解决这道题.
因为如果精心构造数据的话,昨天的题解还是会被卡住的.
今天中午睡觉的时候突然想起一个不会被卡住的方法.
但是由于早上玩了一会类似与宠物消消的弱智游戏,于是怎么也停不下来了.
一个下午的时光也浪费在了这个弱智游戏上.
到了晚上,手机终于没电了,于是来写写这道题的完美解决方法.
这样无论怎么构造数据,tiankonguse都不用担心程序超时了.
正文
题意
有一棵树,树的每个点有点权,每次有三种操作: 1. Query x 表示查询以x为根的子树的权值和。 2. Change x y 表示把x点的权值改为y(0<=y<=100)。 3. Root x 表示把x变为根。 现在度度熊想请更聪明的你帮助解决这个问题。
背景
这篇记录和昨天那一篇紧密相连,建议看看那个记录.
传送门(http://tiankonguse.com/record/record.php?id=673)
背景简述
对于这道题,首先需要对树按1为根优先编号.
编号的时候记录子树的权值和以及子树的编号范围.
这样设置根的一般复杂度是O(1), 修改的一般复杂度是O( log( n ) ), 查询的一般复杂度也是 O( log( n ) ).
修改的最坏复杂度是O( n ), 我们可以使用线段树来优化到O( log( n ) ).
对于查询分了三部分,其中有一部分最坏情况下复杂度也是 O( n ).
当时往二分优化上想了,但是目前的信息不满足二分的条件,所以二分不了.
二分优化查询
假设目前查询的是x, root 是根, y 是x的某个儿子, root 在 y 的那个子树上.
问题1:我们要二分搜索什么?
我们要搜索y这个节点.
问题2:搜索的序列有递增或递减的特增吗?
我们要搜的区间是 left[x]到 left[root], 其中 left[x] 最小,left[y] 不能确定在那个地方,也不知道 left[y] 的值.
问题三:有人说可以使用欧拉序列加树状数组做这道题,是吗?
欧拉序列是什么呢?
原来欧拉序列也对树dfs编号了,只不过进入每个儿子的时候都对当前子树根编号,最后结束时再遍一次号,储存的信息貌似很丰富.
问题四:如果我们也使用欧拉序列或者欧拉序列的思想,可以二分吗?
貌似可以.
因为这时x的每个儿子前面一定有一个编号是x.
而我们需要的是 root 前面的第一个 x.
又由于 x 是区间内最小值,所以通过二分这个最小值就可以搜到 y 了.
问题五:最坏复杂度怎么呀?
由于需要二分,所以最少是 O( log( n ) ).
每次都需要判断,所以这个我们需要通过线段树来优化,可以优化到 log( n ).
这样综合复杂度就是 O( log( n ) ^ 2 )
问题六:那你能实现吗?
这个当然可以,就是一个二分加线段树.
总结
针对昨天遗留下的问题,这里简单的总结一下解决方法.
遗留的问题是查询的时候,如果root是查询节点x的子孙时,我们需要找到x的某个儿子y,这个儿子y还是root的祖先.
这个查找过程用昨天的方法最坏复杂度是O( n ) 的.
这里我找到一个方法:对树dfs编号的时候,每次在儿子前面都添加一个根节点,即把用根节点把各个儿子为根的子树分开.
这样我们就可以使用二分查找x的儿子y了.
因为root前面第一个编号为x的节点和y前面第一个编号为x的节点是相同的.
而且第一个编号为x的节点的下一个节点就是y节点.
由于x还是整个区间的最小值,所以我们就可以通过二分区间最小值来找到root前面的第一个编号为x的节点了.
代码
二分优化查询(其他的暴力的代码)https://github.com/tiankonguse/ACM/blob/master/astar/2014/3/2.3.cpp
完整版的代码(两个线段树写为一个了):https://github.com/tiankonguse/ACM/blob/master/astar/2014/3/2.4.cpp
参考
无
相关推荐
2006年的百度之星程序设计大赛复赛中,第四题便是基于这个游戏机制设定的算法挑战。本题要求参赛者编写程序解决Zuma游戏中的消除策略,以达到最高的得分效率。 在Zuma游戏中,玩家控制一个可移动的彩球,目标是通过...
标题中的“百度之星2010复赛 A+B问题代码(参考)”指的是一个编程竞赛的问题,这通常是指参赛者需要解决的一个基础算法题目。在编程竞赛中,A+B问题是一个非常经典且基础的题目类型,它要求参赛者编写程序来计算两...
【标题】和【描述】提及的是两道程序设计竞赛题目,分别是“好心的出租车司机”和“Robots.txt 协议”。这两道题目考察的是参赛者的算法设计和错误处理能力,同时也涉及到实际问题的解决。 在“好心的出租车司机”...
百度之星09复赛题目 8个小时4道题 百度之星程序设计大赛由百度公司发起创办于2005年,旨在为广大程序设计爱好者搭建一个比试身手、切磋交流的平台。09年百度之星程序设计大赛是连续举办的第五届。大赛每年邀请喜欢...
NOIP2017普及组复赛解题报告 本文档是 NOIP2017 普及组复赛的解题报告,包含三道题的解题思路和代码实现。下面将逐一介绍每道题的知识点和解决方法。 第一题:成绩 score 这道题目非常简单,考察了基本的运算符...
2014年天津市合泰杯 复赛技术报告汇编 由于>60M,所以分为两部分上传
### 百度之星2011试题合集分析 #### 图标排列问题解析 ##### 问题背景 在百度应用平台上,工程师们面临一个问题:如何更好地推荐应用给用户,以提高用户体验。他们注意到,同一开发者开发的应用往往具有相似的图标...
根据【压缩包子文件的文件名称列表】: "百度之星大赛",我们可以推测这个压缩包内可能包含了一系列子文件夹或文件,每个都对应着不同阶段的比赛,比如“初赛题目”、“复赛题目”、“官方答案”、“选手解题思路”等...
【NOIP2009普及组复赛解题报告】 本次解题报告主要涉及两道题目,分别是多项式输出和分数线划定。 **第一题:多项式输出** 这是一道要求根据输入的多项式系数,按照特定格式输出多项式的题目。算法分析如下: 1....
【百度之星历年试题】是关于中国著名互联网巨头百度举办的一项技术竞赛——百度之星的历年考试题目集合。这个压缩包包含了2005年至2007年以及2011年的初赛和复赛试题,格式为PDF,方便学习者进行查阅和练习。 百度...
### NOIP2017普及组复赛解题报告知识点详解 #### T1: 预编译指令、文件操作及输入输出 本题考察的是编程基础能力,具体包括: - **预编译指令**:预编译指令是C/C++语言的一个特性,用于在程序编译之前对源代码...
《百度之星程序设计大赛:2005-2010年试题解析》 自2005年起,百度公司主办的"百度之星"程序设计大赛成为每年一度的IT界盛事,吸引了无数编程爱好者和专业选手参与。该比赛不仅检验了参赛者的编程技巧,也推动了...
### 百度之星十年试题集知识点总结 #### 百度之星程序设计大赛概览 - **背景介绍**:“百度之星”是由百度公司主办的一项面向全国大学生的程序设计竞赛,自2005年起至今已成功举办多届。该比赛旨在通过算法挑战激发...
NOIP2014普及组复赛试题涉及的知识点涵盖了数据结构、算法设计、编程语言的使用以及计算机科学的相关概念。以下是对标题和部分内容中涉及知识点的详细解析: 1. 珠心算测验题目解析 珠心算测验题目要求选手对一个正...
《2014年NOIP真题解析:C与C++编程挑战》 全国青少年信息学奥林匹克联赛(NOIP)是中国计算机学会举办的一项年度赛事,旨在选拔和培养优秀的计算机编程人才,尤其是青少年群体。2014年的NOIP比赛包含了普通组、提高...
ASP.NET 2.0 ,VS 2005 开发
《NOIP提高组复赛历届(1998~2014)题目整合——探索OI之路》 中国的全国奥林匹克信息学竞赛(NOIP)是面向中学生的计算机编程比赛,旨在培养青少年的信息技术能力,选拔优秀的编程人才。提高组复赛作为其中的重要...