地址:https://codeforces.com/contest/1167/problem/E
思路:保存下标对其由小到大排序,当序列其原下标也是由小到大排序的才是合法的。因此对于删除区间[l,r] 是可以枚举 l, 在找出合法序列的最小值 r 的,写起来有些麻烦,先找出 l 最大可以枚举到的位置L,已经右区间r最左边的合法处R。那么在枚举l时更新R使其序列合法即可。
可以看看这位大佬的博客https://www.cnblogs.com/xyq0220/p/10875872.html
Code:
#include<iostream>
using namespace std;
typedef long long LL;
const int MAX_S=1e6+5;
int n,m,s;
int l[MAX_S],r[MAX_S];
int main()
{
ios::sync_with_stdio(false);
cin>>n>>s;
for(int i=1,x;i<=n;++i)
{
cin>>x;
if(!l[x]) l[x]=i;
r[x]=i;
}
int L=1,R=s,Min=0;
while(L<s){
if(l[L]&&l[L]<Min) break;
if(r[L]) Min=r[L];
++L;
}
Min=1e7;
while(R>1){
if(l[R]&&r[R]>Min) break;
if(l[R]) Min=l[R];
--R;
}
LL ans=0;
if(R==1&&r[1]<Min) ans=(LL)s*(s+1)/2,L=0;
Min=0;
int pr=R,p=0;
for(int i=1;i<=L;++i)
{
while(R<s){
if(l[R]&&l[R]>Min) break;
if(l[R]) pr=R;
++R;
}
if(R<=s&&l[R]&&l[R]<Min) pr=R;
ans+=s-pr+1;
if(r[i]) Min=r[i];
if(!p&&r[i]){
p=1; ++R;
}
}
cout<<ans<<endl;
return 0;
}