E. Range Deleting
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given an array consisting of nn integers a1,a2,…,ana1,a2,…,an and an integer xx. It is guaranteed that for every ii, 1≤ai≤x1≤ai≤x.
Let's denote a function f(l,r)f(l,r) which erases all values such that l≤ai≤rl≤ai≤r from the array aa and returns the resulting array. For example, if a=[4,1,1,4,5,2,4,3]a=[4,1,1,4,5,2,4,3], then f(2,4)=[1,1,5]f(2,4)=[1,1,5].
Your task is to calculate the number of pairs (l,r)(l,r) such that 1≤l≤r≤x1≤l≤r≤x and f(l,r)f(l,r) is sorted in non-descending order. Note that the empty array is also considered sorted.
Input
The first line contains two integers nn and xx (1≤n,x≤1061≤n,x≤106) — the length of array aa and the upper limit for its elements, respectively.
The second line contains nn integers a1,a2,…ana1,a2,…an (1≤ai≤x1≤ai≤x).
Output
Print the number of pairs 1≤l≤r≤x1≤l≤r≤x such that f(l,r)f(l,r) is sorted in non-descending order.
Examples
input
Copy
3 3 2 3 1
output
Copy
4
input
Copy
7 4 1 3 1 2 2 4 3
output
Copy
6
Note
In the first test case correct pairs are (1,1)(1,1), (1,2)(1,2), (1,3)(1,3) and (2,3)(2,3).
In the second test case correct pairs are (1,3)(1,3), (1,4)(1,4), (2,3)(2,3), (2,4)(2,4), (3,3)(3,3) and (3,4)(3,4).
題意:
給n個數和x,讓你找出來有多少f(l,r) (1 <= l,r <= x),被刪去後可以使得當前的數列變成非遞減序列
定義:f(l,r)代表所有數中l到r的數
思路:
假如現在有f(l,r)是滿足的,那麼說明所有1~(l - 1)最後出現的位置要< (r + 1)~x第一次出現的位置,另外對於每個1~(l - 1)個元素所有的i 和 i - 1也要滿足這個條件,即i - 1的最右邊要<i的最左邊,r + 1到x也是一樣。如果這樣的話,對於f(l,r)就可以繼續r++,或者l--,他都是會滿足這個條件的,所以就可以利用雙指針來計數
處理出每個數出現的最左邊和最右邊,然後再跑前綴和後綴,對於1~i,所有數出現的最大下標,對於i~n所有數出現的最小的下標,再跑出可以滿足刪除f(l,r)條件的前後綴,l、r最遠位置,pre,post是前後綴最遠的位置,precan、postcan是是否滿足前後綴可行
代碼:
int l[maxn],r[maxn];
int precan[maxn],postcan[maxn],vis[maxn];
int pre[maxn],post[maxn];
bool check(int ll,int rr){
if(!precan[ll - 1] || !postcan[rr + 1]) return false;
if(pre[ll - 1] > post[rr + 1]) return false;
return true;
}
int main(){
ios::sync_with_stdio(false);
int x;
while(cin >> n >> x){
for(int i = 1;i <= n;i++) cin >> a[i],vis[a[i]] = 1;
MS0(l),MS0(r);
memset(l,INF,sizeof(l));
for(int i = 1;i <= n;i++){
if(l[a[i]] == INF) l[a[i]] = i;
r[a[i]] = i;
}
memset(post,INF,sizeof(post));
for(int i = 1;i <= x;i++){
pre[i] = max(pre[i - 1],r[i]);
}
for(int i = x;i >= 1;i--) post[i] = min(post[i + 1],l[i]);
l[x + 1] = INF,r[x + 1] =INF ;
precan[0] = postcan[x + 1] = 1;
int l1 = INF,r1 = 0;
for(int i = 1;i <= x;i++){
if(!vis[i] ){
if(precan[i - 1]) precan[i] = 1;
}else if(precan[i - 1] && l[i] >= r1){
precan[i] = 1;
if(r[i] ) r1 = max(r1,r[i]);
}
}
for(int i = x;i >= 1;i--){
if(!vis[i]){
if(postcan[i + 1]) postcan[i] = 1;
}else if(postcan[i + 1] && r[i] <= l1){
postcan[i] = 1;
if(l[i])
l1 = min(l1,l[i]);
}
}
int L = 1,R = 1; ll ans = 0;
while(R <= x){
while(L > R) R++;
while(R < x && !check(L,R)) R++;
// cout << L << " --- " << R << endl;
if(check(L,R)) ans += x - R + 1 ;
L++;
}
wt(ans);
}
return 0;
}