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;
}
posted @ 2021-11-27 21:56  0x3fffffff  阅读(25)  评论(0编辑  收藏  举报