CCF-CSP 202012-2 期末预测之最佳阈值
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int m;
scanf("%d",&m);
vector<int> result0,result1; //数组result0,result1分别存放挂科,未挂科的学生的安全指数
for(int i = 0; i < m; i++){
int y,res;;
scanf("%d %d",&y,&res);
if(res == 0){
result0.push_back(y);
}else result1.push_back(y);
}
sort(result0.begin(),result0.end());
sort(result1.begin(),result1.end()); //对数组result0和result1中的安全指数分别排序
int maxtruesum = 0,maxtruey = -1; //最多的预测正确数以及其对应的安全指数(即阈值)
for(int i = result0.size()-1; i >= 0; i--){
int mid,low = 0,high = result1.size()-1,truesum; //折半查找
while(low <= high){
mid = (low + high)/2;
if(result0[i] < result1[mid]) high = mid-1;
else if(result1[mid] < result0[i]) low = mid+1;
else break;
}
int midl = mid,midr = mid;
while(result1[midl-1] == result1[mid]) midl--;
while(result1[midr+1] == result1[mid]) midr++; //result1中可能有元素==result1[mid],找相等元素的左右边界
while(result0[i-1] == result0[i]) i--;
//result0中可能有元素==result0[i],跳过去,方便计算result0中<result0[i]的元素个数,同时减少i以减少总循环次数
// 预测正确数 = result0中<阈值的元素个数 + result1中>=阈值的元素个数
//result0中<result0[i]的元素个数为i,根据折半查找结果可求出在result1中>=result0[i]的元素个数
if(low > mid) truesum = i+(result1.size()-1-midr);
else if(high < mid) truesum = i+(result1.size()-midl);
else truesum = i+(result1.size()-midl);
if(truesum > maxtruesum){ //若预测正确数更多
maxtruesum = truesum;
maxtruey = result0[i];
}else if(truesum == maxtruesum && result0[i] > maxtruey){ //若预测正确数相等且安全指数更大
maxtruey = result0[i];
}
}
for(int i = 0; i < result1.size(); i++){
int mid,low = 0,high = result0.size()-1,truesum;
while(low <= high){
mid = (low + high)/2;
if(result1[i] < result0[mid]) high = mid-1;
else if(result0[mid] < result1[i]) low = mid+1;
else break;
}
int midl = mid,midr = mid;
while(result0[midl-1] == result0[mid]) midl--;
while(result0[midr+1] == result0[mid]) midr++;
//result1中>=result1[i]的元素个数为result1.size()-i,根据折半查找结果可求出在result0数组中<result1[i]的元素个数
if(low > mid) truesum = midr+1+(result1.size()-i);
else if(high < mid) truesum = midl+(result1.size()-i);
else truesum = midl+(result1.size()-i);
if(truesum > maxtruesum){
maxtruesum = truesum;
maxtruey = result1[i];
}else if(truesum == maxtruesum && result1[i] > maxtruey){
maxtruey = result1[i];
}
while(result1[i+1] == result1[i]) i++; //跳过安全指数相同的元素,增加i以减少总循环次数
}
printf("%d",maxtruey);
return 0;
}