【CodeForces - 599C 】Day at the Beach (思維)

題意:

給定一個數列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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章