51Nod-2502、2658 最多分成多少块 题解
题目概述
给一个[0, n)的排列的数组,把这个数组分成若干块,对每块进行按升序排序,保证整个数组最后是升序的
问最多能分成几块
思路分析
容易想到的是,如果最后的数组是有序的,首先0应该在第一组中,0前面的元素都要放在第一组,同时因为给出的是一个排列,所以前i个元素排好序后应该刚好是[0, i),即第一组中的所有数字应该恰好是[0, i)的一个排列
所以长度为i的前缀分成第一组的充要条件是:这个前缀的最小值为0,最大值为i
但是由于是一个排列,前i个元素中必定没有相等元素,前i个数的所以最大值为i时,最小值也一定为0
所以长度为i的前缀分成第一组的充要条件是:这个前缀的最大值为i
然后再继续思考:
现在有两个满足条件的前缀,一个长度为a,一个长度为b(a<b),那么他们可以被分成两组,第一组为[0,a),第二组为[a,b)
因为[0, a)排好后,[0,b)的前a个是不动的
遍历数组,如果前i个元素的最大值为i,则组数+1
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long llong;
const int N = 2e5 + 5;
const int MOD = 1e9 + 7;
llong n, a[N];
int main() {
#ifdef LOCAL
freopen("D:/Code/ACM/in.in", "r", stdin);
freopen("D:/Code/ACM/out.out", "w", stdout);
#endif
cin.tie(0)->sync_with_stdio(0);
cin >> n;
llong mx = -1, ans = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
mx = max(mx, a[i]);
if (mx == i) {
ans++;
}
}
cout << ans << "\n";
return 0;
}