zoukankan      html  css  js  c++  java
  • BZOJ 4540 [Hnoi2016]序列 | 莫队 详细题解

    传送门

    BZOJ 4540

    题解

    ……怎么说呢……本来想写线段树+矩阵乘法的……
    ……但是嘛……yali的机房太热了……困……写不出来……
    于是弃疗,写起了莫队。(但是我连莫队都想不出来!)

    首先用单调栈可以轻松求出每个元素左右两边第一个比它小的元素位置,分别设为tl[i]、tr[i]。

    莫队关键就是在一端插入/删除元素时如何维护当前区间的答案嘛,而这就需要快速计算当前区间左/右端点对当前区间的贡献。

    下面以在左边插入一个元素为例,设插入后区间是[l, r]。

    插入这个元素的时候,新增的区间显然是左端点为l、右端点为l~r的所有区间。它们的贡献按照最小值分类,可以分为:最小值为a[l]的、最小值为a[tr[l]]的、最小值为a[tr[tr[l]]]的……最小值为[l, r]区间最小值(它的位置设为p)的。

    那么每个最小值 * 最小值为它的区间个数,再加起来,就是左端点的贡献。

    为了快速求出,可以对每个元素维护一个“前缀和”,表示以这个元素为左/右端点的所有区间的最小值之和,分别设为sr[i]和sl[i]。以sr[i]为例:

    sr[i] = sr[tr[i]] + a[i] * (tr[i] - i)

    然后,区间[l, r]左端点的贡献就是sr[i] - sr[p] + a[p] * (r - p +1)。
    右边a[p] * (r - p + 1)这一块是因为以a[p]为最小值的区间不一定都包含在[l, r]内,有的右端点在r的右面。

    这样,结合莫队,就可以AC了!

    ……(低级失误:用st表维护的是下标,却把值作为初值传了进去……还有把查询时的j打成j-1……)

  • 相关阅读:
    mysql练习题练习
    test
    jquery获取地址栏参数
    Sql Server获取数据库字段名,并用list显示在jsp页面
    javascript主页面获取子页面元素
    javascript常用方法
    jquery.cookie实现刷新页面复选框选定状态不变
    JDBC操作Oracle、SqlServer根据日期查询
    mysql 5.1升级为5.5方法
    innodb二进制文件相关的参数
  • 原文地址:https://www.cnblogs.com/RabbitHu/p/BZOJ4540.html
Copyright © 2011-2022 走看看