1. 程式人生 > 其它 >CSP202012-2 期末預測之最佳閾值

CSP202012-2 期末預測之最佳閾值

技術標籤:練習題目演算法資料結構c++

CSP202012-2 期末預測之最佳閾值

題目

題目可以在CSP的官網檢視到喲!

演算法思想

這道題要做的就是尋找最佳的閾值,使得預測正確的數量最多。看過最後的資料範圍,發現2<=m<=100000,這道題很容易想到O(n * n)的演算法,但是肯定會超時,因此需要一個時間複雜度較低的演算法。接下來,小編介紹的演算法時間複雜度是O(n*logn)。
首先對閾值進行排序,按照閾值從大到小進行排序,可以很容易地想到,在選擇的閾值之前的預測為0的是預測正確的,在閾值之後的預測為1的是預測正確的,因此提前生成兩個陣列,一個數組記錄該點 之前預測為0的數量,另一個數組記錄該點之後(包括該點)預測為1的數量,而對於該點,兩個陣列相加就是以該點數值為閾值的預測正確的數量。

還有一個問題,就是如果存在多個相同的安全指數,該怎麼辦呢,小編手動模擬了出現相同多個安全指數的情況,發現:相同的安全指數,預測為1的排在前面,預測為0的排在後面,就可以得到正確的答案。因此在利用sort快速排序的時候,先按照安全指數從小到大排序,再按照預測值從1到0排序即可。
排序之後,利用字首和和字尾和的思想,分別統計某一點之前預測為0的數量以及某一點之後(包括該點)預測為1的數量,之後尋找兩者相加最大值所對應的最大閾值即可。

完整程式碼

#include<iostream>
#include<cstdio>
#include<algorithm>
#pragma
warning (disable:4996)
using namespace std; int m; struct Person { int y, result; }person[200000]; int sum0[200000], sum1[200000]; bool cmp(Person a, Person b) { if (a.y != b.y) return a.y < b.y; else return a.result > b.result; } int main() { freopen("in.in", "r", stdin); freopen
("out.out", "w", stdout); int i, j; cin >> m; for (i = 1; i <= m; i++) cin >> person[i].y >> person[i].result; sort(person + 1, person + m + 1, cmp); sum0[0] = 0; sum0[1] = 0; for (i = 2; i <= m; i++) { if (person[i - 1].result == 0) sum0[i] = sum0[i - 1] + 1; else sum0[i] = sum0[i - 1]; } sum1[m + 1] = 0; for (i = m; i >= 1; i--) { if (person[i].result == 1) sum1[i] = sum1[i + 1] + 1; else sum1[i] = sum1[i + 1]; } int max_y = 0, max_num = 0; for (i = 1; i <= m; i++) { int num = sum0[i] + sum1[i]; if (num >= max_num) { max_y = person[i].y; max_num = num; } } cout << max_y << endl; return 0; }