今年后半年开始重新看CCF真题,看到2020年的一道题,发现不太会题目很有水平,于是选择借鉴一手,然后就发现了自己的题解(大无语事件
看了一下发现是前缀和,后缀和的问题,和前几天刷的一道题,CCF 2021-04-2 邻域均值一样,都是前缀和的问题,这里记录一下
思路
跟我之前写的思路大差不差,只是在细节上更改了一些具体前缀和,后缀和的求法。
大概来说,前缀和就是记录每一次计算中在前一次计算已经计算过的重复部分,然后节省时间,进行优化的一种手段。
代码
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct {
int y;
int result;
}student;//学生结果
typedef struct{
int y;
int nopass;
int passed;
int less_equal; //前缀和
int bigger_equal;//后缀和
}record;//记录
int const N = 100005;
student s[N];
record r[N];
bool comp(student a,student b){
return a.y < b.y;
}
int main(){
int m;
cin>>m;
for(int i = 0;i < m;i++){
cin>>s[i].y>>s[i].result;
}
sort(s,s+m,comp);
r[0].y = s[0].y;
int j = 0;
for(int i = 0;i < m;){
if(s[i].y == r[j].y){
if(s[i].result == 1){
r[j].passed++;
}else{
r[j].nopass++;
}
i++;
}else{
j++;
r[j].y = s[i].y;
}
}
//前缀和
for(int i = 0 ; i <= j;i++){
if(i != 0){
r[i].less_equal = r[i-1].less_equal + r[i].nopass;
}else{
r[i].less_equal = r[i].nopass;
}
}
//后缀和
for(int i = j ;i >= 0 ;i--){
if(i != j)
r[i].bigger_equal = r[i + 1].bigger_equal + r[i].passed;
else
r[i].bigger_equal = r[i].passed;
}
int sum_max = 0;
int sumPredicit = r[j].y;
for(int i = j ; i >= 0;i--){
if(sum_max < r[i].less_equal + r[i].bigger_equal - r[i].nopass){
sum_max = r[i].less_equal + r[i].bigger_equal - r[i].nopass;
sumPredicit = r[i].y;
}
}
cout<<sumPredicit;
}