「CF1167E」Range Deleting【双指针】
E. Range Deleting
You are given an array consisting of integers and an integer . It is guaranteed that for every , .
Let’s denote a function which erases all values such that from the array and returns the resulting array. For example, if then
Your task is to calculate the number of pairs such that and is sorted in non-descending order. Note that the empty array is also considered sorted.
Input
The first line contains two integers and — the length of array and the upper limit for its elements, respectively.
The second line contains integers
Output
Print the number of pairs such that is sorted in non-descending order.
Examples
input
3 3
2 3 1
output
4
input
7 4
1 3 1 2 2 4 3
output
6
Note
In the first test case correct pairs are and
In the second test case correct pairs are and
题意
- 就是给你一个序列,然后你可选择两个数和使得,使得删去序列中所有满足的数后序列非严格递减,问有多少对可行的,空序列满足条件
题解
-
由于非递减序列的子序列荏苒非递减,所以对于删去一段区间的数后,所有大于的数的最小位置一定大于所有小于的数的最大位置,首先可以预处理出弱删除或者的所有数后剩下的所有数是否构成非递减序列,并且分别记录剩下的数的最左边位置和最右边位置,最后枚举左端点,用另外一个指针去找最小的满足以下几个条件
- 删去的数剩下的数非递减
- 删去的数剩下的数中最左边数的位置删去后剩下的数中最右边的数的位置
然后即可
代码
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e6+10;
int n,x,a[maxn],l[maxn],r[maxn];
vector<int> pos[maxn];
bool canl[maxn],canr[maxn];
int main()
{
scanf("%d %d",&n,&x);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),pos[a[i]].push_back(i);
int p=inf;
memset(canl,false,sizeof(canl));
memset(canr,false,sizeof(canr));
for(int i=x+1;i>=1;i--) {
if(pos[i].empty()) {
canl[i-1]=true;
l[i-1]=p;
continue;
}
if(pos[i].back()<=p) {
canl[i-1]=true;
l[i-1]=p=pos[i][0];
}else break;
}
p=-1;
for(int i=0;i<=x;i++) {
if(pos[i].empty()) {
canr[i+1]=true;
r[i+1]=p;
continue;
}
if(pos[i][0]>p) {
canr[i+1]=true;
r[i+1]=p=pos[i].back();
}else break;
}
long long ans=0;int point=0;
for(int i=1;i<=x&&canr[i];i++) {
while(point<x&&(point<i||!canl[point]||l[point]<r[i])) point++;
ans+=(x-point+1);
}
printf("%lld\n",ans);
}