202109-2非零段划分


題目

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

總結

  1. 在函數內部定義過大的函數時會爆棧,我第一次寫的時候(暴力法),每次改變p值時都在循環內定義一個新數組來存儲改變后的數組。然后程序也沒有報錯,但是運行時就是自己中斷了,問了大佬才知道原來在還是內部定義太大的數組時會爆棧,所以以后盡量把函數定義在main函數前。
  2. 加深理解前綴和,了解了差分這種算法。我發現最近幾年CCF的第二題好像都用到了前綴和,要多多練習掌握!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM