首页 > 其他分享 >F. MEX vs MED

F. MEX vs MED

时间:2022-10-26 11:48:06浏览次数:78  
标签:MED med text MEX 枚举 vs 端点 区间 mex

F. MEX vs MED

You are given a permutation $p_1,p_2, \dots ,p_n$ of length $n$ of numbers $0, \dots ,n−1$. Count the number of subsegments $1 \leq l \leq r \leq n$ of this permutation such that $mex(p_l, p_{l+1}, \ldots, p_r) > med(p_l, p_{l+1}, \ldots, p_r)$.

$mex$ of $S$ is the smallest non-negative integer that does not occur in $S$. For example:

  • $mex({0, 1, 2, 3}) = 4$
  • $mex({0, 4, 1, 3}) = 2$
  • $mex({5, 4, 0, 1, 2}) = 3$

$med$ of the set $S$ is the median of the set, i.e. the element that, after sorting the elements in non-decreasing order, will be at position number $\left \lfloor{ \frac{|S| + 1}{2} } \right \rfloor$ (array elements are numbered starting from $1$ and here $\left \lfloor{v} \right \rfloor$ denotes rounding $v$ down.). For example:

  • $med({0, 1, 2, 3}) = 1$
  • $med({0, 4, 1, 3}) = 1$
  • $med({5, 4, 0, 1, 2}) = 2$

A sequence of $n$ numbers is called a permutation if it contains all the numbers from $0$ to $n−1$ exactly once.

Input

The first line of the input contains a single integer $t$ $(1 \leq t \leq {10}^{4})$, the number of test cases.

The descriptions of the test cases follow.

The first line of each test case contains a single integer $n$ $(1 \leq n \leq 2 \cdot {10}^{5})$, the length of the permutation $p$.

The second line of each test case contains exactly $n$ integers: $p_1,p_2, \dots ,p_n$ $(0 \leq p_i \leq n−1)$, elements of permutation $p$.

It is guaranteed that the sum of $n$ over all test cases does not exceed $2 \cdot {10}^{5}$.

Output

For each test case print the answer in a single line: the number of subsegments $1 \leq l \leq r \leq n$ of this permutation such that $mex(p_l, p_{l+1}, \ldots, p_r) > med(p_l, p_{l+1}, \ldots, p_r)$.

Example

input

8
1
0
2
1 0
3
1 0 2
4
0 2 1 3
5
3 1 0 2 4
6
2 0 4 1 3 5
8
3 7 2 6 0 1 5 4
4
2 0 1 3

output

1
2
4
4
8
8
15
6

Note

The first test case contains exactly one subsegment and $mex({0}) = 1 > med({0}) = 0$ on it.

In the third test case, on the following subsegments: $[1,0]$, $[0]$, $[1,0,2]$ and $[0,2]$, $mex$ is greater than $med$.

In the fourth test case, on the following subsegments: $[0,2]$, $[0]$, $[0,2,1]$ and $[0,2,1,3]$, $mex$ greater than $med$.

 

解题思路

  对于这种统计类的问题关键在于如何划分集合使得计数的过程能够做到不重不漏。一般来对于一个序列我们会根据右端点来划分集合,然后枚举右端点来求解满足要求的答案。这里的话可以发现枚举右端点是不行的,因为整个过程的时间复杂度会比较高。

  因此这里要选择另外的方式来划分集合。我们根据$\text{mex}$来划分集合。根据定义,如果某个序列的$\text{mex} = i$,那么这个序列必须包含$0 \sim i - 1$,并且不能包含$i$。因为整个序列是一个排列,因此我们可以记录每个数字的下标位置$\text{p[i]}$,然后预处理数字$0 \sim i$这个前缀的最小下标和最大下标,记为$\text{minp[i]}$和$\text{maxp[i]}$。$\text{minp[i]}$表示数字$0 \sim i$中最小的下标位置,$\text{maxp[i]}$表示数字$0 \sim i$中最大的下标位置。因此对于某个$\text{mex} = i$,应该满足$\text{p[i]} < \text{minp[i]} \,\,\text{and}\,\, \text{p[i]} > \text{maxp[i]}$。

  现在要找出所有$\text{mex} = i$的区间,看看有多少个区间满足$\text{mex} > \text{med}$。可以发现在$\text{mex} = i$的区间中,必定包含$0 \sim i - 1$(一共$i$个元素),其余的元素都是严格大于$i$的,如果区间长度不超过$2i$,那么这个区间的$\text{med}$必定小于$i$,如果区间长度超过$2i$,那么$\text{med}$必定大于$i$。只要区间的长度不超过$2i$,那么就是符合条件的答案。

  即现在我们要枚举$\text{mex}$值,找到包含数字$0 \sim i - 1$的长度最小的区间(即区间$[\text{minp[i]}, \text{maxp[i]}]$),然后根据左右端点往外延拓,统计包含这个最小长度的区间,且区间长度不超过$2i$的区间数目(这里的统计就是根据端点来划分集合了)。这里往外延拓既可以选择枚举右端点求满足条件的左端点数目,也可以枚举左端点求满足条件的右端点数目。

  考虑一种情况,如果已经找到了$\text{mex} = i$的最小区间$[l, r]$,并且$\text{p[i]} < l$,我们都选择枚举右端点求左端点数目。然后$i + 1$又在$i$的左边,此时$\text{mex} = i + 1$的最小区间为$[\text{p[i]}, r]$,继续选择枚举右端点求左端点数目。如果之后的数字都出现在上一个数字的左边,又因为我们每次都从$r$往后枚举,因此时间复杂度会变成$O(n^2)$。这意味着我们要选择合理的枚举方式。

  具体来说是这样的,对于$\text{mex} = i$的最小区间$[l, r]$,如果$\text{p[i]} > r$,即$i$在区间的右边,这时我们应该枚举右端点求满足条件的左端点数目。如果如果$\text{p[i]} < l$,即$i$在区间的左边,这时我们应该枚举左端点求满足条件的右端点数目。这样我们就可以遍历的过程中不重复地枚举$n$个位置(因为枚举的位置下一次就变成$\text{mex} = i+1$的最小区间,即每次枚举的位置都会变少),因此整个时间复杂度为$O(n)$。

  AC代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 2e5 + 10;
 7 
 8 int p[N], minp[N], maxp[N];
 9 
10 void solve() {
11     int n;
12     scanf("%d", &n);
13     for (int i = 0; i < n; i++) {
14         int x;
15         scanf("%d", &x);
16         p[x] = i;
17     }
18     
19     p[n] = n;    // mex = n,按理来说n不会出现在序列中,因此我们把n定义在序列之外
20     minp[0] = maxp[0] = p[0];    // 初始时数字0的就是一个区间
21     for (int i = 1; i < n; i++) {
22         minp[i] = min(minp[i - 1], p[i]);    // 求数字1~i的最小下标
23         maxp[i] = max(maxp[i - 1], p[i]);    // 求数字1~i的最大下标
24     }
25     
26     LL ret = 0;
27     for (int i = 1; i <= n; i++) {    // mex = 0时,没有满足要求的区间,因此从mex = 1开始
28         if (p[i] >= minp[i - 1] && p[i] <= maxp[i - 1]) continue;    // i在最小区间范围内
29         int len = 2 * i;
30         if (p[i] < minp[i - 1]) {    // i在最小区间左边
31             for (int j = minp[i - 1]; j > p[i]; j--) {    // 枚举左端点
32                 if (j + len - 1 < maxp[i - 1]) break;    // 区间[j, j + len - 1]没有覆盖最小区间
33                 ret += min(n - 1, j + len - 1) - maxp[i - 1] + 1;    // 左端点固定,满足条件的右端点范围就在[maxp[i-1], j+len-1]
34             }
35         }
36         else {
37             for (int j = maxp[i - 1]; j < p[i]; j++) {    // 枚举左端点
38                 if (j - len + 1 > minp[i - 1]) break;    // 区间[j - len + 1, j]没有覆盖最小区间
39                 ret += minp[i - 1] - max(0, j - len + 1) + 1;    // 右端点固定,满足条件的左端点范围就在[j-len+1, minp[i-1]]
40             }
41         }
42     }
43     
44     printf("%lld\n", ret);
45 }
46 
47 int main() {
48     int t;
49     scanf("%d", &t);
50     while (t--) {
51         solve();
52     }
53     
54     return 0;
55 }

 

参考资料

  Codeforces Round #828 (Div. 3) E, F:https://zhuanlan.zhihu.com/p/574230639

标签:MED,med,text,MEX,枚举,vs,端点,区间,mex
From: https://www.cnblogs.com/onlyblues/p/16827677.html

相关文章

  • VS2019编译驱动时出现Inf2Cat错误
    1.VS2019编译驱动时出现Inf2Cat错误:2.解决方法如下,修改项目属性->Inf2Cat->General->UseLocalTime项为"/uselocaltime".......
  • [Typescript] 68. Medium - Fill
    Fill,acommonJavaScriptfunction,nowletusimplementitwithtypes. Fill<T,N,Start?,End?>,asyoucansee,Fill acceptsfourtypesofparameters,ofwh......
  • MEX 相关
    基础理解静态求mex:O(n)。动态加点/删点求mex:我们维护一个set表示没有出现过的集合。那么O(n\logn)。CF1732D2https://zhuanlan.zhihu.com/p/576620849......
  • 90V瞬态电压抑制(TVS)二极管选型及型号选用
    TVS二极管选型过程中,涉及到的主要参数有:工作峰值反向电压、击穿电压、钳位电压、峰值脉冲电流、峰值脉冲功率、测试电流、漏电流、封装形式。其中,TVS的工作峰值反向电压是第......
  • vscode调试C++代码,及makefile
      launch.json{//使用IntelliSense了解相关属性。//悬停以查看现有属性的描述。//欲了解更多信息,请访问:https://go.microsoft.com/fwlink/?......
  • linux LVS的NAT工作模式
    LVS:lvs是一个负载均衡的一个集群软件,由内核集成,性能强大,支持百万计并发。LVS集群的相关概念:VS:虚拟服务器,指LVS服务器自身RS:提供服务的服务器CIP:客户端ip地址......
  • vs引用管理器简介
    https://blog.csdn.net/hhw199112/article/details/80437011  右侧四个选项,程序,COM,项目,浏览。项目和浏览很好理解。程序和COM的区别在哪里?可以这样理解COM是非基于......
  • ddd领域驱动设计模型 及 Net6使用MediatR完成领域事件发送
    十年河东,十年河西,莫欺少年穷学无止境,精益求精1、序言领域驱动设计是一种解决业务复杂性的设计思想,不是一种标准规则的解决方法。 2、ddd领域驱动模型介绍参考:https:......
  • 构建 Flutter 应用程序的10个最佳 VSCode 插件
    构建Flutter应用程序的10个最佳VSCode插件在本文中,我们将分享使用VisualStudio代码(VSCode)IDE的经验。我们的开发团队更喜欢使用某些插件,这里我们将解释原因......
  • [Typescript] 67. Medium - Chunk
    Doyouknow lodash? Chunk isaveryusefulfunctioninit,nowlet'simplementit. Chunk<T,N> acceptstworequiredtypeparameters,the T mustbea tu......