题目来源:- 计算机软件能力认证考试系统
如果采用暴力解法,则会运行超时,只能得80分,所以我们采用前缀和方法来解题,这个思想主要用来求指定区间和。
定义式 | 递推式 | |
一维前缀和 | ![]() | ![]() |
思路分析:
- 使用vector+结构体进行存储,并将输入的阈值进行排序。
- 然后我们求出前缀和,将这个阈值作为最佳阈值后,计算比当前阈值低的有多少个人不挂科。
- 注意sum[0]=0,因为当前阈值是不挂科的。
- 挂科的人数(no):当前阈值的排名(i-1)减去当前阈值的前缀和(sum[i-1]),即减去不挂科的人数。
- 不挂科的人数(yes):所有的不挂科的人数(sum[m])减去当前阈值前一个阈值不挂科的人数(sum[i-1])。
- 然后进行比较看有没有超过最值,超过就更新,因为成绩从小到大,而我们又要同等数量的最大值,所以跑到最后就行了。
- 注意这里采用set来查重,防止出现错误。
set.count()函数的用法:
count(val) | 在当前 set 容器中,查找值为 val 的元素的个数,并返回。注意,由于 set 容器中各元素的值是唯一的,因此该函数的返回值最大为 1。 |
下面是此题AC代码。
#include<bits/stdc++.h>
using namespace std;
struct node {
int value;
int result;
};
bool cmp(node a,node b) {
if(a.value<b.value) return true;
else return false;
}
int main() {
ios::sync_with_stdio(false);
int n;
cin>>n;
node t;
vector<node> v;
for(int i=0; i<n; i++) {
cin>>t.value>>t.result;
v.emplace_back(t);
}
sort(v.begin(),v.end(),cmp);
int sum[100010]={0};
for(int i=1; i<=n; i++)
sum[i]=sum[i-1]+v[i-1].result;
int yes,no,max_result=0,max_value;
set<int> s;
for(int i=1; i<=n; i++) {
if(s.count(v[i-1].value))
continue;
s.emplace(v[i-1].value);
yes=sum[n]-sum[i-1];
no=i-1-sum[i-1];
if(yes+no>=max_result) {
max_result=yes+no;
max_value=v[i-1].value;
}
}
cout<<max_value;
return 0;
}
下面是二维前缀和的介绍和例题解答。