• 连续段计数问题小记


    给定一个长度为 \(n\) 的一个排列,如果区间 \([l,r]\) 之间的数是连续的,那么我们称这个区间时一个连续段。

    比如 \([1,3,2,5,4]\) 中的连续段有:\([1,1],[1,3],[1,5],[2,2],[2,3],[2,5],[3,3],[4,4],[4,5],[5,5]\)

    这些连续段有一个共同的特点:区间长度等于值域大小,即 \(\max-\min+1=r-l+1\)

    移项可得:\(\max-\min-r+l=0\),判断是否为连续段就采用的是这种方法。

    有一些题目会询问关于连续段的问题,很多都是数区间个数。数区间个数的问题一般可以分治固定端点,下边就采用了固定端点的方法,枚举右端点,处理所有左端点的询问。

    由于上面我们需要通过维护 \(\max,\min\) 维护每个左端点。前面的 \(\max,\min\) 可以用单调栈维护,整体用线段树记录,(好像也叫扫描线?)

    那么我们就来看一些具体问题吧!

    CF526F Pudding Monsters

    给定长度为 \(n(n\le 3\times 10^5)\) 的排列,求其中连续段数量。

    枚举右端点,用单调栈更新左端点,每次询问 \(0\) 的个数。

    CF997E Good Subsegments

    给定长度为 \(n(n\le 1.2\times 10^5)\) 的排列,有 \(q(q\le 1.2\times 10^5)\) 次询问,每次询问一段区间 \([l,r]\) 内的连续段数量。

    好像是上一题的严格加强版捏。

    其他和上面一模一样,我们还需要维护历史答案,那就改改线段树吧!

    如果直接维护 \(0\) 的个数会比较麻烦,但是题目中有一个重要的性质保证给定的是排列。这表示 \(\max-\min-r+l\) 一定 \(\ge 0\)只有区间最小值会被减为 \(0\)。那么记下最小值和次数即可。

    具体维护以下信息:

    • 当前区间最小值 \(valnowmin\)
    • 当前区间最小值个数 \(cntnowmin\)
    • 当前增加值 \(vallaz\)
    • 这个区间有多少次最小值到达了 \(0\) 但子节点里没有计入答案 \(pushed\)
    • 答案数量 \(ans\)

    每移动一次右端点记录给整棵树加一次 \(pushed\) 即可。

    P4747 [CERC2017]Intrinsic Interval

    给定长度为 \(n(n\le 10^5)\) 的排列,有 \(q\) 次询问,每次询问包含区间 \([l,r]\) 的最短连续段。

    \(\bigstar\texttt{Hint}\):如果有两个包含 \([l,r]\) 的连续串 \([l_1,r_1],[l_2,r_2]\)(不妨令 \(l_1<l_2\)),下面证明 \([l_2,r_1]\) 一定是连续串。

    由于 \([l_1,r_1],[l_2,r_2]\) 都是连续串,\([l_1,r_1]\) 内值域连续,\([l_2,r_2]\) 内值域连续。

    有因为两区间有交,所以交内的数一定是两区间值域的交,所以也是连续的。

    接下来问题就是:对于每个询问,找到第一个满足条件的右端点,使得存在一个连续段包含它。

    \(\bigstar\texttt{Trick}\):照样枚举右端点,每次取出处理当前的和以前的未处理的最靠右的左端点,询问它是否合法,如果合法继续,不合法停止。

    这样再线段树里维护区间内最靠右的 \(0\) 即可。

    P6795 [SNOI2020] 排列

    luogu 数据锅了?还好 loj 没锅。。那就咕咕咕了吧。

  • 相关阅读:
    JMeter
    MeasureSpec介绍及使用详解
    AS中一些不经常用到的快捷键
    gradle 构建工具,与Ant Maven关系
    关于runOnUiThread()与Handler两种更新UI的方法
    关于new Handler()与new Handler(Looper.getMainLooper())区别
    RTSP协议详解
    overridePendingTransition的简介
    Android获取手机分辨率DisplayMetircs类
    RTSP消息交互过程
  • 原文地址:https://www.cnblogs.com/EricQian/p/16551619.html
Copyright © 2020-2023  润新知