首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

杭電 ACM 4520 題解:小Q系列——最佳裁判 (貪心 + 排序 + 多重集)

     編輯:關於C語言

題目大意 (重構)

小 Q 擔任裁判,需對選手得分進行處理,去除最高最低分後求平均,或類似的「去極值統計」問題。核心是貪心策略 + 高效數據結構維護有序序列。

核心算法


#include 
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m; // n 選手, m 裁判
    while (cin >> n >> m) {
        vector> scores(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                int x; cin >> x;
                scores[i].insert(x);
            }
        }

        for (int i = 0; i < n; i++) {
            auto& ms = scores[i];
            // 去除最高最低
            ms.erase(ms.begin());       // 最低
            ms.erase(prev(ms.end()));   // 最高

            // 計算平均
            long long sum = 0;
            for (int v : ms) sum += v;
            double avg = (double)sum / ms.size();
            cout << fixed << setprecision(2) << avg << "\n";
        }
    }
    return 0;
}

關鍵點解析

  1. multiset 自動有序:紅黑樹實現,插入/刪除/查找 O(log m),自動處理重複分數。
  2. 去極值:begin() 最小,prev(end()) 最大。erase(iterator) 只刪一個元素 (關鍵!erase(value) 會刪所有相等值)。
  3. 精度控制:用 long long 累加避免溢出,double 除法,setprecision(2) 保留兩位小數。
  4. 多測試用例:while (cin >> n >> m) 讀到 EOF 結束。

優化:前綴和數組 (若 m 固定、多次查詢)


// 若每個選手分數固定,預排序存 vector,前綴和 O(1) 區間求和
vector> a(n, vector(m));
for (auto& v : a) { sort(v.begin(), v.end()); }
vector> pref(n, vector(m+1));
for (int i=0;i

適合離線、只讀場景,比 multiset 快得多。

常見坑點

坑點後果修正
ms.erase(val)刪除所有等於 val 的元素用 ms.erase(ms.find(val)) 或迭代器
整數除法精度丟失轉 double 再除
m=2 時去極值後空集除零崩潰題目保證 m≥3 或特判
輸出格式格式錯誤 WAfixed << setprecision(2) 強制兩位小數

複雜度

  • multiset 版:O(n * m log m)。
  • 排序+前綴和版:O(n * m log m) 預處理,O(1) 查詢。
  • 空間:O(n * m)。

延伸:流式數據去極值平均

若分數流式到達,需動態維護去極值平均,可用雙堆 (大根堆存小半、小根堆存大半) + 延遲刪除 或平衡 BST (policy_based_data_structure) 實現 O(log m) 插入/刪除/查詢中位數/去極值和。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved