辉夜大小姐想让我构造不降序列 双指针+思维
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
/*
题解:
首先得到 f(1,r) 的一个区间,然后容易得到 f(2,x) 这个x>r(这个可以自己思考一下)
所以就有点像双指针。
对于每一个区间 f(l,r),我都应该判断 l-1 之前的都是顺序的,r+1之后都是顺序的
并且最小的 (r+1,n) 的位置要大于最大的 (1,l-1) 这个位置
*/
int lc[maxn],rc[maxn],L[maxn],R[maxn],pre[maxn],last[maxn];
bool check(int x,int y){
if(pre[x-1]&&last[y+1]&&L[y+1]>R[x-1]) return true;
return false;
}
int main(){
int n,x;
scanf("%d%d",&n,&x);
memset(L,inf,sizeof(L));
memset(lc,inf,sizeof(lc));
for(int i=1,v;i<=n;i++) {
scanf("%d",&v);
lc[v] = min(lc[v],i);
rc[v] = max(rc[v],i);
}
for(int i=x;i>=1;i--){
L[i] = min(L[i+1],lc[i]);
}
for(int i=1;i<=x;i++){
R[i] = max(R[i-1],rc[i]);
}
pre[0] = 1;
for(int i=1;i<=x;i++){
pre[i] = pre[i-1]&(R[i-1]<lc[i]);
}
last[x+1] = 1;
for(int i=x;i>=1;i--){
last[i] = last[i+1]&(L[i+1]>rc[i]);
}
ll ans = 0;
int now = 1;
for(int i=1;i<=x;i++){
while(now<i) now++;
while(now<=x&&!check(i,now)) now++;
if(check(i,now)) ans+= x - now + 1;
}
printf("%lld
", ans);
}