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……)

  • 相关阅读:
    hdu 4651 Partition (利用五边形定理求解切割数)
    单点登录SSO的实现原理
    高速排序算法
    2014 百度之星第三题
    TR069协议向导——一个帮助你了解TR069协议的简明教程(一)
    教你用笔记本破解无线路由器password
    人脸识别算法初次了解
    JSP验证码
    GROUP BY,WHERE,HAVING之间的差别和使用方法
    typedef函数指针使用方法
  • 原文地址:https://www.cnblogs.com/RabbitHu/p/BZOJ4540.html
Copyright © 2011-2022 走看看