这道题要根据给出的公式计算最优值,但贸然照抄公式是会导致O(n^2)的时间复杂度,只能得70分,满分需要使用时间复杂度O(n)的算法。
思路:
首先确定最终结果的计算式,对于每个学生来说,他的安全指数可以预测正确的数目为(安全指数比他低且挂科的学生数+安全指数不低于他且未挂科的学生数),进而拆分可以得到通式,Res(i) = A0+A1+A2+……+A(i-1)+Bi+B(i+1)+……+Bn
其中Ai表示安全指数i下挂科的学生数,Bi表示安全指数i下未挂科的学生数。
对每个学生维护一个Stu结构体,记录对应的安全指数与挂科情况,还有使用该学生作为阈值对应的正确数量;同时再维护一个map,用于记录每种分数下通过的学生数与未通过的学生数。
以下为代码,仍有很大优化空间:
#include
#include
#include
using namespace std;
struct Stu{
int Y;
int result;
int nCorrect;
};
bool cmp(Stu s1,Stu s2){
if (s1.Y<s2.Y)
{
return true;
}
return false;
}
int main()
{
//first=0 , second=1
map<int,pair<int,int> > oRecord;
int m;
cin>>m;
vector<Stu> s;
for (int i = 0; i < m; i++)
{
int a,b;
cin>>a>>b;
Stu tmp;
tmp.Y=a;
tmp.result=b;
tmp.nCorrect=0;
s.push_back(tmp);
}
sort(s.begin(),s.end(),cmp);
for (int i = 0; i < m; i++)
{
if (s[i].result==0)
{
oRecord[s[i].Y].first++;
}
if (s[i].result==1)
{
oRecord[s[i].Y].second++;
}
if ((s[i].Y>=s[0].Y&&s[i].result==1)||
(s[i].Y<s[0].Y&&s[i].result==0))
{
s[0].nCorrect++;
}
}
for (int i = 1; i < m; i++)
{
if (s[i].Y==s[i-1].Y)
{
s[i].nCorrect = s[i-1].nCorrect;
continue;
}
if (s[i].Y>s[i-1].Y)
{
s[i].nCorrect = s[i-1].nCorrect+(oRecord[s[i-1].Y].first)-(oRecord[s[i-1].Y].second);
}
}
int nmax=0;
int nRes=0;
for(int i=0;i<m;++i)
{
Stu obj=s[i];
if (obj.nCorrect>nmax)
{
nmax = obj.nCorrect;
nRes = obj.Y;
}
if (obj.nCorrect==nmax)
{
nRes=obj.Y>nRes?obj.Y:nRes;
}
}
cout<<nRes;
return 0;
}