202012 csp
- 1.期末预测之安全指数
题目背景
期末要到了,小菜同学找到了自己的好朋友顿顿,希望可以预测一下自己这学期是否会挂科。
题目描述
首先,顿顿选取了如“课堂表现”、“自习时长”、“作业得分”、“社团活动参与度”等 项指标作为预测的依据。
然后,顿顿根据自己平日里对小菜的暗中观察,以百分制给每一项指标打分,即小菜同学第 i项指标的得分
是一个[0,100] 范围内的整数。
鉴于每一项指标的重要性不尽相同,顿顿用一个 [-10,10] 范围内的整数
来表示第i项指标的重要程度。
最后,小菜同学期末的安全指数y定义如下:
y=sigma(w[i]*score[i])
其中 ReLU(x)=max(0,x)是一种常见的激活函数。
因为使用了 ReLU 函数,安全指数一定是个非负值。
如果安全指数过低(甚至为零),则说明小菜同学这学期很可能要挂科了……
已知每一项指标的重要程度和相应的得分 ,快来算算小菜同学期末的安全指数吧。
输入格式
从标准输入读入数据。
输出格式
输出到标准输出。
输出一个非负整数 ,表示小菜同学期末的安全指数。
样例1输入
6
2 60
10 100
0 70
0 0
-10 50
10 60
样例1输出
1220
样例2输入
2
-10 100
-1 15
样例2输出
0
#include<iostream>
#include<vector>
using namespace std;
int n;
class Class{
public:
int w;
int score;
};
int main(){
vector<Class> v;
cin>>n;
for(int i=0;i<n;i++){
int score,w;
cin>>w>>score;
Class c = {w,score};
v.push_back(c);
}
int sum =0;
for(int i=0;i<v.size();i++){
sum+=v[i].w*v[i].score;
}
if(sum<0) sum=0;
cout<<sum;
return 0;
}
- 2.期末预测之最佳阈值
样例1输入
6
0 0
1 0
1 1
3 1
5 1
7 1
样例1输出
3
样例2输入
8
5 1
5 0
5 0
2 1
3 0
4 0
100000000 1
1 0
样例2输出
100000000
70分
#include<iostream>
#include<vector>
using namespace std;
int n;
int ans = 0;
class Student{
public:
int y;
int result;
};
int main(){
cin>>n;
vector<Student> v;
for(int i=0;i<n;i++){
int y;
int result;
cin>>y>>result;
Student s ={y,result};
v.push_back(s);
}
int maxt = 0;
//最大预测正确次数
int maxn = 0;
//最大预测正确次数的sita
//超时 n<=10^5
for(int i =0;i<n;i++){//sita
int tmp=0;
for(int j=0;j<n;j++){
if(v[j].y>=v[i].y){
if(v[j].result==1) tmp++;
}else{
if(v[j].result==0) tmp++;
}
}
if(maxt<tmp){
maxt=tmp;
maxn=v[i].y;
}else if(maxt==tmp){
maxt=tmp;
maxn=max(maxn,v[i].y);
}
}
cout<<maxn;
return 0;
}
优化的思路是去掉重复的操作,根据观察发现
(1)若θ1<θ2,yi>=θ2,则yi一定>=θ1
(2)若θ1<θ2,yi<=θ1,则yi一定<=θ2
所以每次更新时只需要更新[θ1,θ2)的,用index保存θ1的值
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n;
int ans = 0;
class Student{
public:
int y;
int result;
};
bool cmp(Student &s1,Student &s2){
return s1.y<s2.y;
}
int main(){
cin>>n;
vector<Student> v;
for(int i=0;i<n;i++){
int y;
int result;
cin>>y>>result;
Student s ={y,result};
v.push_back(s);
}
sort(v.begin(),v.end(),cmp);
int maxt = 0;
//最大预测正确次数
int maxn = 0;
//最大预测正确次数的sita
//n<=10^5
//初始化
int tmp=0;
int index=0;
maxn=v[0].y;
for(int i=0;i<n;i++){
if(v[i].result==1) tmp++;
}
maxt=tmp;
//只需要更新此次sita之前的
for(int i =1;i<n;i++){//sita
int flag;
while (v[index].y < v[i].y) {
// θ值相等时结果相同,只计算一个
if (v[index].y < v[i].y)
flag = 0;
else
flag = 1;
if (flag == v[index].result)
tmp++;
else
tmp--;
index++;
}
if(maxt<tmp){
maxt=tmp;
maxn=v[i].y;
}else if(maxt==tmp){
maxt=tmp;
maxn=max(maxn,v[i].y);
}
}
cout<<maxn;
return 0;
}
还有一种使用前缀和后缀和的方式
#include <iostream>
#include <algorithm>
using namespace std;
const int M = 100000;
pair<int, int> a[M + 1];
int prefix[M + 2], suffix[M + 2], p[M + 2];
int main()
{
int m, i;
cin>>m;
for(i = 1; i <= m; i++)
cin>>a[i].first>>a[i].second;
sort(a + 1, a + 1 + m);
// 前缀和
prefix[0] = 0;
for(i = 1; i <= m; i++)
prefix[i] = prefix[i - 1] + (a[i].second == 0 ? 1 : 0);
//相错一位 所以后面p[i]要-1
// 后缀和
suffix[m + 1] = 0;
for(i = m; i >= 1; i--)
suffix[i] = suffix[i + 1] + (a[i].second == 1 ? 1 : 0);
int pos = 1;
p[1] = 1;
for(i = 1; i <= m; i++)//处理θ相同
if(a[i].first == a[i - 1].first)
p[i] = pos;
else
p[i] = (pos = i);
int ans = 0, mx = 0;
for(i = 1; i <= m; i++) {
int cur = prefix[p[i] - 1] + suffix[i];
if(cur >= mx)
mx = cur, ans = a[i].first;
}
cout<<ans;
return 0;
}
ljm要加油