chenchen題解:CSP-J2019第二次錯題整理

飛炫少仔發表於2020-10-08

下面是關於CSP-J2019的第二次錯題整理:

  • 在這裡插入圖片描述

解釋:挨個試,對於每一個數x從二開始試,直到根號x

  • #include<cstdio> using namespace std; int n, m; int a[100], b[100];
    
    int main() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i)
            a[i] = b[i] = 0;
        for (int i = 1; i <= m; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            if (a[x] < y && b[y] < x) {
                if (a[x] > 0)
                    b[a[x]] = 0;
                if (b[y] > 0)
                    a[b[y]] = 0;
                a[x] = y;
                b[y] = x;
            }
        }
        int ans = 0;
        for (int i = 1; i <= n; ++i) {
            if (a[i] == 0)
                ++ans;
            if (b[i] == 0)
                ++ans;
        }
        printf("%d", ans);
        return 0; } ```
    

在這裡插入圖片描述

解釋:
在這裡插入圖片描述

  • #include <iostream> using namespace std; const int maxn = 10000; int n; int a[maxn]; int b[maxn]; int f(int l, int r, int depth) {
        if (l > r)
            return 0;
        int min = maxn, mink;
        for (int i = l; i <= r; ++i) {
            if (min > a[i]) {
                min = a[i];
                mink = i;
            }
        }
        int lres = f(l, mink - 1, depth + 1);
        int rres = f(mink + 1, r, depth + 1);
        return lres + rres + depth * b[mink]; } int main() {
        cin >> n;
        for (int i = 0; i < n; ++i)
            cin >> a[i];
        for (int i = 0; i < n; ++i)
            cin >> b[i];
        cout << f(0, n - 1, 1) << endl;
        return 0; } ```
    

在這裡插入圖片描述
在這裡插入圖片描述
解釋(1):
f()中返回lres + rres + depth * b[mink],如果b[]全為0,結果一定為0
解釋(2):
已知b[0] = 1, b[1] = 2, ..., b[9] = 10,要輸出最大值,即depth * b[mink]的和最大,那麼depth的值應該儘可能的大。與上道題類似,陣列a[]中元素是有序的,才能保證歸深度最大,最大值= 1 × 1 + 2 × 2 + 3 × 3 + . . . + 10 × 10 = 385

  • (計數排序)計數排序是一個廣泛使用的排序方法。下面的程式使用雙關鍵字計數排序,對 n 對 10000 以內的整數,從小到大排序。

    例如有三對整數(3,4)、(2,4)、(3,3),那麼排序之後應該是(2,4)、(3,3)、(3,4)。

    輸入第一行為 nn,接下來 nn 行,第 ii 行有兩個數 a[i] 和 b[i],分別表示第 ii 對整數的第一關鍵字和第二關鍵字。

    提示:應先對第二關鍵字排序,再對第一關鍵字排序。陣列 ord_____ 儲存第二關鍵字排序的結果,陣列 res_____
    儲存雙關鍵字排序的結果。

    試補全程式

  • #include <cstdio>
    #include <cstring> using namespace std; const int maxn = 10000000; const int maxs = 10000;
    
    int n; unsigned a[maxn], b[maxn],res[maxn], ord[maxn]; unsigned
    cnt[maxs + 1]; int main() {
        scanf("%d", &n);
        for (int i = 0; i < n; ++i)
            scanf("%d%d", &a[i], &b[i]);
        memset(cnt, 0, sizeof(cnt));
        for (int i = 0; i < n; ++i); // 利用 cnt 陣列統計數量
        for (int i = 0; i < maxs; ++i)
            cnt[i + 1] += cnt[i];
        for (int i = 0; i < n; ++i); // 記錄初步排序結果
        memset(cnt, 0, sizeof(cnt));
        for (int i = 0; i < n; ++i); // 利用 cnt 陣列統計數量
        for (int i = 0; i < maxs; ++i)
            cnt[i + 1] += cnt[i];
        for (int i = n - 1; i >= 0; --i)// 記錄最終排序結果
        for (int i = 0; i < n; i++)
            printf("%d %d",);
    
        return 0; }
    
    

解釋:
計數排序,通過統計每個待排序元素的出現次數,實現排序。本題中,cnt[]陣列分別統計了兩個關鍵字陣列中每個元素的出現次數,同時又進一步處理了在區間 (0,10000)中,前i個數中小於等於i的關鍵字個數,可以計算每個關鍵字的排名。
陣列 ord[] 和陣列 res[] 都是以排名為下標,記錄關鍵字在陣列中的位置。陣列 ord[] 儲存第二關鍵字排序的結果,ord[i] = j表示排名為i的第二個關鍵字在陣列b[j]中。陣列 res[] 儲存雙關鍵字排序的結果,res[i] = j表示最終排名為i的關鍵字在陣列a[j]、b[j]中。
空①,題目中提示先對第二個關鍵字排序,所以次空應填:cnt[b[i]]++,記錄所有第二個關鍵字的出現次數。
空②,記錄初步排序結果。通過上面程式碼cnt[i + 1] += cnt[i];,cnt[i]儲存了小於等於i的第二關鍵字的個數,那麼cnt[b[i]即表示小於等於關鍵字b[i]的關鍵字個數,即b[i]的排名。題目中提示ord[]儲存第二關鍵字排序的結果,此處應將處理結果儲存到陣列ord[]中,即ord[--cnt[b[i]]] = i--cnt[b[i]保證了排名從0~n-1,同時,b[i]的出現次數減少一次。
空③,利用 cnt 陣列統計第一個關鍵字的數量,所以次空應填:cnt[a[i]]++
空④,通過上面程式碼cnt[i + 1] += cnt[i];cnt[i]儲存了小於等於i的第一關鍵字的個數,cnt[a[i]]即表示小於等於關鍵字a[i]的關鍵字個數,即a[i]的排名。cnt[a[ord[i]]]表示排名為i的第二關鍵字在陣列位置ord[i],其對應的雙關鍵字的排名為cnt[a[ord[i]]],它所在陣列的位置為ord[i]。所以此空應填:res[--cnt[a[ord[i]]]] = ord[i]
空⑤,陣列 res[] 儲存雙關鍵字排序的結果,所以次空應填:a[res[i]], b[res[i]]
在這裡插入圖片描述

相關文章