• 可持久/可回退化数据结构


    可持久化数据结构用来解决这个问题:
    1.在某个版本的基础上修改,同时生成新的版本
    2.查询某个版本的值。
    直接复制版本十分浪费。
    为了查询以前的信息,可以不动以前的节点,只建新节点。
    这就是可持久化数据结构的思想。
    可回退化数据结构比上面的更弱。它用来解决这个问题:
    1.在当前版本上进行修改
    2.回退一步
    这个数据结构的要求比普通数据结构更强,但是比可持久化数据结构更弱。
    可以使用一个栈,存储被修改的位置,回退的时候再撤销。
    但是很多时候,不能直接这么做。
    比如可回退化单调栈,上面这么做时间复杂度是错的。
    因为每次插入以后可能删除很多元素。
    可以使用二分。由于栈中的元素是单调的,可以二分到需要弹栈的位置,然后把栈顶设为这个位置。
    这样子时间复杂度就是正确的。
    此外,上面两个数据结构都需要保证无论输入数据怎么样,操作时间复杂度都是一个较低的值val。
    可持久化数据结构有这么一个转化:
    如果把这个点向生成它的版本连边,则形成一颗树。
    这棵树从某节点到根经过的操作就是这个版本经过的修改操作。
    dfs整颗树,在到一个节点时插入,离开一个节点的时候删除。
    则可持久化问题转化为更弱的可回退化问题。
    例题:
    可持久化数组

    使用可持久化线段树维护

    可持久化并查集(没做)

    使用可持久化数组。
    并查集要只加按秩合并,复杂度才正确。

    可持久化平衡树(没做)
    codechef WEASELSC

    由于题目的楼梯可递增/递减,所以可以把楼梯翻转后再做一遍。
    通过观察,我们可以发现这两个引理:
    1.所有楼梯的高度都在(a)里出现过。
    2.设(l_i)表示(a)(i)左边第一个(<a_i)的位置。
    如果我们第i个位置选择了(a_i),则(l_i+1)(i)都要选择(a_i)
    这是因为如果不选择(a_i),结果不会更好。楼梯数不会更少
    有了这两个引理,我们显然可以设dp方程。
    (f_{k,i})表示有(k)个阶梯,目前dp到i。
    (f_{k,i}=max(f_{k-1,j}+(i-j)*a_j),j<i,a_j<a_i)
    如果(j<i)(a_j<a_i),则把(j)作为(i)的父亲。
    问题转化为:
    有一颗树,每个节点有一条直线,求出某个点(x)到根的所有直线截(x=k)的最大值。
    这是个经典的问题。可以通过从根建可持久化李超树/有根树点分治等方法解决。

    集训队互测 unknown

    一道论文题。可以看论文。

    动态半平面交
    七彩树(没做,上面一道题弱化版)
    异或粽子

    如果我们要求全局最大xor和,则可以trie树。
    这是个trie树经典问题。
    如果要求区间最大xor和,把它差分成前缀最大xor和。
    可以可持久化trie树。
    每次最多会修改log个节点。
    如果要求k大xor和,则根据经典套路可以二分/堆。
    取k次最大值,每次拓展出可能成为解的位置即可。

    购票

    [NOI2018]你的名字

    bzoj二分图

    简单线段树分治。
    需要可回退化数据结构

    bzoj城市建设

    显然可以线段树分治。
    但是线段树分治需要支持动态最小生成树,支持回退。
    使用lct,连边把环上权值最小的边删除,回退cut即可。

    codechef FBCHEF

    https://www.cnblogs.com/ctmlpfs/p/13677219.html

    CF757G

    CF1037H

    一道比较简单的字符串数据结构题。
    题目要求字典序严格(>)询问串且最小。
    可以使用一个简单的贪心。解一定是贪心的让构造的串匹配最长长度+一个严格>原串该位置的最小字符。
    考虑求出构造的串匹配的最长长度。这是个基本的sam+线段树合并/sam+可持久化线段树+dfs序匹配问题。
    我们要知道是否有(pin [l,r])(p-len+1in [l,r])其中len=匹配的长度。
    合起来就是(pin [l+len-1,r])
    (nxt_i)表示(i)节点后的最小字符。没有设为(-1)
    (nxt_i)可以通过求出构造的串匹配的最长长度的方法求出。
    枚举(lcp)即可得到答案/判定无解。

    CF464E(没做)
    [IOI2015]分组(忘了)
    HNOI2019 JOJO(忘了)
    loj3225(没做)
    jzoj4611(没做)
    loj 网格图
    jzoj5750

    CF1063F
    挖掘性质:
    引理1:如果我们倒过来选,显然每次选比上次长度+1的最优。
    如果不是这么选,则找到从字符串长度小到大第一个不符合这个条件的串。
    然后通过从这个串的首/尾删除/插入字符。把这个串的长度变成上一个串的长度+1。
    容易发现这样子依然合法。
    (f_i)表示(i)作为开头最多能选几个。
    如果我们枚举一个长度(md),表示现在的(f_i)
    则要求对于([i+md,n])的区间存在一个(j)使得(lcp(i,j)>=md-1)(lcp(i+1,j)>=md-1)
    引理2:(md)可以二分。即如果存在以(i)为结尾的长度为(md)的解,也存在(i)为结尾的长度为(md-1)的解。
    我们可以把所有解中,存在对应(dp_i)的最后一位的位的串拿掉,再删除重复的串的最上面一个。
    容易知道,最上面的一个在原来如果长度为(le+1),则重复的串的最下面一个长度为(le)
    且最上面的一个重复串存在对应(dp_i)的最后一位的位。
    所以可以删除。
    所以可以二分(md)
    然而数据范围达到了5e5,这样子肯定是不可取的。
    引理3:(f_i-1<=f_{i+1})
    如果把现在(f_i)的首位字符删除,则可以使用类似引理2的方法证明答案最多会小1。
    移项得到(f_i<=f_{i+1}+1)
    所以我们可以先把(f_i=f_{i+1}+1),然后不断令(f_i--),判定是否满足要求。
    我们要求对于([i+md,n])的区间存在一个(j)使得(lcp(i,j)>=md-1)(lcp(i+1,j)>=md-1)
    由于第一个条件的区间终点是(n),所以可以倒着建可持久化线段树。
    第二/三个条件,满足条件的肯定在后缀数组上是连续的一段,可以二分+st表求出。
    查询这两个区间最大值是否(>=md-1)即可。
    时间复杂度(nlog_2n)

    loj6198

    比较简单的字符串数据结构题。
    有两种做法:
    1.sa。
    根据经典结论,两个字符串的lcp等于它在sa上的rmq。
    考虑分治。每次取出最值分治。
    这样子好处在于lcp是一定的。
    接下来我们要求一个串对一个区间串的xor和的最大值。
    这是个经典的问题。可以trie树解决。
    但是直接分治时间复杂度是错误的。根据套路可以使用较小的xor较大的区间贡献答案。
    根据启发式合并/轻重链剖分的复杂度,这样子时间复杂度是正确的
    2.sam
    根据经典结论,两个字符串的lcp等于它在sam parent树上的lca深度。
    建立反串的sam。
    dfs parent树。
    我们要统计两个trie树的贡献。
    这可以对trie树进行dfs。
    当dfs到某个节点x时,枚举当前节点的第一个trie树选什么,根据大小关系得知它和哪个节点xor。
    做完后把trie树合并到根即可。
    (其实线段树分治,回滚莫队都需要可回退化数据结构,并且要求时间复杂度严格正确)

  • 相关阅读:
    Omi框架学习之旅
    Omi框架学习之旅
    Omi框架学习之旅
    加密解密
    RSA加密解密
    CMDB后台管理(AutoServer)
    CMDB Autoclient思路分析
    CMDB开发(需求分析)
    Django之model操作(续)
    Django之Model操作
  • 原文地址:https://www.cnblogs.com/ctmlpfs/p/13657045.html
Copyright © 2020-2023  润新知