題目
http://118.190.20.162/view.page?gpid=T130
題目圖片

思路一:暴力法(70分)
我的做法是:先做一個判斷非零段的函數,然后依次去p值,將數組中小於p的值置0,將改變后的數組導到一個新的數組中,調用判斷函數判斷非零段,然后取max值。
然后,我判斷非零段的方法也很簡單,碰到非零的就+1,然后把非零的全部遍歷完,再碰到非零的還這樣,以此類推......
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int arr[N],n;
int ss[N];
int judge(int num[], int n) {
int cnt = 0;
for (int i = 0; i < n; i++) {
if (num[i] != 0) {
cnt++;
while (num[i] != 0) i++;
}
}
return cnt;
}
int maxn(int num[], int n) {
int maxn = -1;
for (int i = 0; i < n; i++) {
if (num[i] > maxn) maxn = num[i];
}
return maxn;
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
int maxnn = maxn(arr, n);
int cnt = 0,p=0;
for (int i = 1; i <= maxnn; i++) {
for (int j = 0; j < n; j++) {
if (arr[j] < i) ss[j] = 0;
else ss[j] = arr[j];
}
p=judge(ss,n);
cnt=max(p,cnt);
}
cout << cnt;
return 0;
}
思路二:前綴和+差分(100分)
#include <iostream>
using namespace std;
const int N = 1e6;
int dif[N], a[N];
int n;
void add(int l, int r) { dif[l]++, dif[r + 1]--; }
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) {
if (a[i - 1] < a[i]) {
add(a[i - 1] + 1, a[i]);
}
}
int maxn = 0, pre = 0;
for (int p = 1; p < 1e4; p++) {
pre += dif[p];
maxn = max(maxn, pre);
}
cout << maxn;
return 0;
}
理解
這個要用到前綴和以及差分的思想,在這里寫的話就顯得篇幅太長了,另寫博文描述。請看下面的文章:
https://www.cnblogs.com/yongcheng137blogs/p/15412952.html
總結
- 在函數內部定義過大的函數時會爆棧,我第一次寫的時候(暴力法),每次改變p值時都在循環內定義一個新數組來存儲改變后的數組。然后程序也沒有報錯,但是運行時就是自己中斷了,問了大佬才知道原來在還是內部定義太大的數組時會爆棧,所以以后盡量把函數定義在main函數前。
- 加深理解前綴和,了解了差分這種算法。我發現最近幾年CCF的第二題好像都用到了前綴和,要多多練習掌握!
