题目链接:http://acm.dlut.edu.cn/problem.php?id=1327
题目:(不知道外面能不能上 = =)
Description
Shik loves sorted intervals. But currently he does not have enough time to sort all the numbers. So he decided to use Almost sorted intervals. An Almost sorted interval is a consecutive subsequence in a sequence which satisfies the following property:
The first number is the smallest.
The last number is the largest.
Please help him count the number of almost sorted intervals in this permutation.
Note: Two intervals are different if at least one of the starting or ending indices are different.
Input
Muti-case , for each case
The first line contains an integer N.
The second line contains a permutation from 1 to N
1<=n<=10^6
Output
Output the number of almost sorted intervals.
Sample Input
53 1 2 5 4
Sample Output
8
HINT
Explanation
The subsequences [3], [1], [1 2], [1 2 5], [2], [2 5], [5], [4] are almost sorted intervals.
首先,我们能用单调队列求出来点i作为区间左端点的时候的最大的可能的右端点范围,为[i,r[i]]。然后求完之后,从右向左进行单调队列的过程,维护最大值,当把点i放进单调队列的时候,单调队列中的点都大于等于点i的值,也就是可能作为右端点,这时候还需要满足点i作为左端点的时候能够覆盖右端点,于是二分寻找,就得到了每个点作为左端点的值,然后得到最终结果。
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
using namespace std;
#define ll long long
const int maxn = 1e6+10;
struct Node{
int val,tt;
}node[maxn],mmin[maxn],mmax[maxn];
struct NN{
int tt,r;
}rr[maxn];
int r[maxn];
void get_min(int n){
int head = 0,tail = -1;
for(int i = 0;i < n;i ++){
while(tail >= head&&mmin[tail].val >= node[i].val){
r[mmin[tail].tt] = i-1;
tail --;
}
mmin[++ tail] = node[i];
}
}
ll ans;
int get(int l,int r,int vv){
int m;
while(l < r){
m = (l+r)>>1;
if(mmax[m].tt > vv)l = m+1;
else r = m;
}
return l;
}
void get_max(int n){
int head = 0,tail = -1;
for(int i = n-1;i >= 0;i --){
while(tail >= head&&mmax[tail].val <= node[i].val){
tail --;
}
mmax[++ tail] = node[i];
//for(int i = head;i <= tail;i ++)cout<<mmax[i].val<<'_';cout<<endl;
//cout<<i<<' '<<tail-get(head,tail,(r[i] == -1?n:r[i]))+1<<' '<<(r[i]==-1?n:r[i])<<endl;
ans = ans + tail - get(head,tail,r[i]==-1?n:r[i]) + 1;
}
}
int nn[maxn];
bool cmp(NN a,NN b){
return a.r < b.r;
}
int main(){
int n,k;
while(~scanf("%d",&n)){
memset(r,-1,sizeof(r));
memset(nn,0,sizeof(nn));
for(int i = 0;i < n;i ++){
scanf("%d",&node[i].val);
node[i].tt = i;
}
get_min(n);
ans = 0;
get_max(n);
cout<<ans<<endl;
}
return 0;
}