題意:
給定一個數列A,要求你將這個數列劃分成幾個連續的部分,使得每部分分別從小到大排序後整個數列有序。
問最多可以劃分成幾個部分。
第一行包含一個整數 n (1 ≤ n ≤ 100 000) — 表示數列的長度,之後一行 n 個整數 hi (1 ≤ hi ≤ 109). 描述這個數列。
思路:
當一個數後面沒有比他小的數時,則他與他後面的部分可以斷開,即他自己可以作爲一個單獨的區間。否則,找到後面距離他最遠的比他小的數,然後得到一個區間,這個區間必須要作爲一個整體分割,這樣才能使得區間結尾的數在排序後能到區間開頭的數的前面,然後枚舉區間的每一個元素,維護區間結尾,就是每個數後面比他小距離他最遠的數的位置和當前區間結尾比較。枚舉完區間,這個區間就作爲一段進行分割。
ac代碼:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<vector>
#include<unordered_map>
#define mod (1000000007)
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
struct node{
int val,id;
friend bool operator<(node a,node b){
if(a.val==b.val) return a.id<b.id;
return a.val<b.val;
}
}b[maxn];
int a[maxn],vis[maxn];
int main(){
int n,ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i].id=i,b[i].val=a[i];
sort(b+1,b+1+n);
int id=0;
for(int i=1;i<=n;i++){
if(b[i].id>id) vis[b[i].id]=-1;
else vis[b[i].id]=id;
id=max(id,b[i].id);
}
for(int i=1;i<=n;){
int j;
if(vis[i]==-1) i++;
else{
int ed=vis[i];
for(j=i;j<=ed;j++)
ed=max(vis[j],ed);
i=ed+1;
}
ans++;
}
printf("%d\n",ans);
return 0;
}