zoukankan      html  css  js  c++  java
  • 2018暑假集训专题小结 Part.3

    树套树相关 √

    树套树

    前置技能——
    一大堆的数据结构。
    线段树、权值线段树、树状数组等基本的
    二叉搜索树、平衡树(splay、treap(无旋)、替罪羊等)、
    hash(这个不是数据结构)
    各种可持久化:可持久化线段树(主席树)、可持久化权值线段树、可持久化splay
    高级一点的:zkw线段树、飞旋treap、红黑树、sbt。
    (其实没有必要学那么多)
    (不是滑稽图)
    恩,大概就是什么多了。

    用处——
    处理一些高级的数据结构。
    (废话)
    我们来看看一道题——
    一段区间内,动态修改数字,并且动态求区间第k大。
    离线?
    强制在线!

    那么怎么做?
    我们看到后面的求区间第k大,我们就可以很好地想到主席树或权值线段树。
    那么,我们如何解决动态修改数字的操作呢?
    这个东西线段树、树状数组可以解决。
    那么如何把这两个东东合并起来成为解题利器呢?
    那就是树套树!
    其实树套树很简单理解——
    一个树里面,每个节点又有一棵树(数据结构)。
    恩,就是这个东西。
    我们看看,线段树可以支持修改操作,然后我们还要在这里面维护主席树,那么就可以在线段树的每一个节点上弄一颗主席树,但是,主席树的形态可能会有点难看。
    由于线段树常数大,所以我们看看树状数组怎么弄。
    我们任然在树状数组上建主席树,但是,树状数组不像前缀和一样,所以我们每次查询主席树就用每次向前跳lowbit这样的方法来查询即可。

    然后就是这样做带修主席树的啦。

    那么我们考虑再改改题面——
    每次支持插入、删除、查询第k大。

    那么这个我们也很好搞,像上面的方法一样:
    考虑一个支持插入删除的数据结构——
    平衡树!
    那么我们就考虑splay等平衡树来做,每次就把主席树建立于一个splay节点上。
    然后,我们就可以根据实际情况来查询。
    这真的可行吗?
    可能会由于splay的旋转操作所影响答案,于是我还是推荐用替罪羊树来搞。
    那么treap呢?选择操作依然会影响。
    那么无旋treap?常数太大了。
    所以——
    “替罪羊树特别棒!”

    我们再来看一类问题——
    我们对于一个二维平面,我们每次修改一个矩形,或询问矩形内的最大最小值。

    这个显然是可以用树套树来搞。
    线段树太大了,那么就树状数组套树状数组。
    我们姑且认为这也是树套树。
    然后搞的方法类似的。
    注意:空间很大
    观察到可用的状态不多,每次修改只会修改O(log ^2 n)个节点,
    所以我们可以用hash来储存出现的位置
    这也是为什么前置知识有hash。

    总结一下——
    树套树是一个很神奇的数据结构,功能很多,可以说是没有做不到,只有想不到。
    唯一的缺点——就是数据结构的共同缺点加倍出现——常数极大。
    所以,不到关键时刻,树套树不建议用。
    真的不建议用,因为你可能不小心打错一点地方,那么就很难调,编程难度很大,而且时间、空间、常数等陷阱很可能会坑你。

    于是,我们现在看看例题——
    T1、【gdoi2018 day1】涛涛接苹果 from jzoj5699
    Description
    这里写图片描述
    这里写图片描述
    Input
    这里写图片描述
    Output
    这里写图片描述
    Sample Input
    10 5 6
    1 2 3 4 5 6 7 8 9 10
    9 7
    7 10
    6 5
    7 5
    5 8
    5 1
    2 1
    3 2
    2 4
    2 3 4
    2 9 5
    1 7 3
    4 8 2
    5 6 6
    2 3
    2 5
    1 4
    3 5
    5 1
    6 1

    Sample Output
    0
    43
    4
    27
    11
    13

    Data Constraint
    这里写图片描述
    Hint
    这里写图片描述

    这题做法——CDQ分治+树状数组或树状数组套线段树。
    首先,我们CDQ分治不讲了吧,很好想的。
    树状数组套线段树也是直接做,但是我们要注意一些空间、常数之类的东西。

    T2、【NOIP2016模拟7.8】Dynamic len from jzoj4594
    Description
    有n个数编号从0→n-1,两种操作:
    Q L R:询问编号为L→R-1的数中共有多少种不同的数
    M X Y:将编号为X的数改为Y
    共有m个操作

    Input
    第一行两个数n,m
    接下来m行,每行有两种形式,如题目描述

    Output
    对于每一个Q操作,输出相应的答案

    Sample Input
    7 4
    1 2 1 3 2 1 4
    Q 1 6
    M 3 2
    Q 1 6
    Q 3 5

    Sample Output
    3
    2
    1

    Data Constraint
    30% n,m<=10000
    100% n,m<=50000
    数的范围<=1000000

    这题做法,线段树套权值线段树。
    也很好想到。

    T3、【NOI2014模拟】数列 from jzoj3615
    Description
    给定一个长度为n的正整数数列a[i]。

    定义2个位置的f值为两者位置差与数值差的和,即f(x,y)=|x-y|+|a[x]-a[y]|。

    你需要写一个程序支持2种操作(k都是正整数):

    Modify x k:将第x个数的值修改为k。

    Query x k:询问有几个i满足f(x,i)<=k。询问不仅要考虑当前数列,还要考虑任意历史版本,即统计任意位置上出现过的任意数值与当前的a[x]的f值<=k的对数。(某位置多次修改为同样的数值,按多次统计)

    Input
    第1行两个整数n,q。分别表示数列长度和操作数。

    第2行n个正整数,代表初始数列。

    第3~q+2行每行一个操作。

    Output
    对于每次询问操作,输出一个非负整数表示答案。

    Sample Input
    3 5
    2 4 3
    Query 2 2
    Modify 1 3
    Query 2 2
    Modify 1 2
    Query 1 1

    Sample Output
    2
    3
    3

    Data Constraint
    这里写图片描述

    这题,树状数组套主席树。
    不会想不到吧?

    但是,综上三题,看上去都很好想到,但是,编程复杂度很高,不信你试试我没试过
    而且,在你怒码几千byte的代码时,说不定就打错那么几个小错误,然后就调了几个小时,真的很崩溃。
    所以,真的不建议去死磕。(除非你是那种无脑数据结构选手)

    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    Django restfull规范
    Python3中的zip()
    关于负数的isdigit()判断
    Win7 x64安装Paramiko
    深度学习性能提高
    神经网络激励函数
    机器学习十大算法
    深度学习十大框架比较
    python 换行
    python sort() sorted() 与argsort()函数的区别
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148404.html
Copyright © 2011-2022 走看看