• 洛谷5113


    如果只有1个元素,显然可以维护一个栈。
    赋值相当于在栈中插入一个元素。维护bz[i]表示i操作是否被撤销。
    撤销操作可以不断的把栈中bz=1的元素删除直到栈顶bz=0。
    由于每个元素只会被删除一次,所以时间复杂度正确。
    这给了我们一些启示。
    考虑分块。对于每个块维护一个栈,栈顶表示最后一次有效(没被撤销)的整块赋值。
    还是维护bz[i]表示i操作是否被撤销。
    对于每个元素维护一个栈。
    由于某个元素可能被赋值多次,但是最后每个元素最多被赋值(sqrt{n})次。
    所以使用n个链表维护元素栈。
    维护每个块的和ans。
    在赋值时,对赋值的整块的块栈中都插入一个元素,同时更新ans。
    对散块对赋值操作作用的每个元素栈插入一个元素,且重构被更新的散块。
    在查询时,我们在查询时遍历所有整块,并把它们的ans加起来。
    在查询散块时,取这个散块被整体赋值/单点赋值的最晚操作更新答案。
    在撤销时,更新bz。
    对于整块,删除块顶部bz=1的元素。同时更新ans。如何更新后面会说。
    对于散块,重构整个块。
    在重构时,求出块内每个元素最晚被赋值的时间(a),并且把a以时间从小到大进行排序。
    求出赋的值的后缀和(s)(s_i=s_{i+1}+a_i)
    对于每个块维护last表示块内最晚被重构(最晚被单点赋值)的时间
    对于每个块维护p,表示最小的p使得a[p]>=last
    注意要把(s_0)加上从未被赋值过的元素。
    取出这个块的栈的顶部(最晚的整块赋值)。
    如果这个操作的时间(设为v)>块内元素最晚被散块赋值的时间,则这个块的ans=块的大小。
    否则,把p赋值为0,暴力更新p,这个块的(ans=p*整块赋值的值+s[p])
    同时更新last。
    在删除后更新整块的ans时,更新pt
    取出这个块的栈的顶部(最晚的整块赋值)。
    如果这个操作的时间(设为v)>last,则这个块的ans=块的大小。这是因为在散块赋值后就有个整块赋值,导致散块赋值无效。
    否则,由于在重构前,这个块被撤销的操作的时间都是单调递减的,所以维护p可以暴力把p向前移动。
    为什么是last?因为last前的操作已经被移动过了。
    这个块的(ans=p*整块赋值的值+s[p])
    在排序的时候,如果我们选择基数排序,排序的基为(255)约等于(sqrt{n}),则对cache友好,只会排2次。
    且由于重构操作只有n次,所以时间复杂度为(nsqrt{n})
    类似CF1178G的分析,可以得到时间复杂度为(nsqrt{n})
    综上,我们在(nsqrt{n})的时空复杂度解决了这个问题。

  • 相关阅读:
    安装 oracle
    svn 编辑
    软件构架
    liunx操作
    css的样式分类
    简单自己做了一个个人简历
    网页制作之表格,列表
    MYSQL表创建
    linux操作指令 第二部分
    linux操作指令 第一部分
  • 原文地址:https://www.cnblogs.com/ctmlpfs/p/13740141.html
Copyright © 2020-2023  润新知