期末预测之安全指数
题目描述
首先,顿顿选取了如“课堂表现”、“自习时长”、“作业得分”、“社团活动参与度”等 𝑛 项指标作为预测的依据。 然后,顿顿根据自己平日里对小菜的暗中观察,以百分制给每一项指标打分,即小菜同学第 𝑖(1≤𝑖≤𝑛)项指标的得分 𝑠𝑐𝑜𝑟𝑒𝑖 是一个 [0,100] 范围内的整数。 鉴于每一项指标的重要性不尽相同,顿顿用一个 [−10,10] 范围内的整数 𝑤𝑖 来表示第 𝑖(1≤𝑖≤𝑛)项指标的重要程度。
最后,小菜同学期末的安全指数 𝑦 定义如下:
𝑦=ReLU(∑𝑖=1𝑛𝑠𝑐𝑜𝑟𝑒𝑖⋅𝑤𝑖)
其中 ReLU(𝑥)=max(0,𝑥) 是一种常见的激活函数。 因为使用了 ReLU 函数,安全指数一定是个非负值。 如果安全指数过低(甚至为零),则说明小菜同学这学期很可能要挂科了……
已知每一项指标的重要程度 𝑤𝑖 和相应的得分 𝑠𝑐𝑜𝑟𝑒𝑖,快来算算小菜同学期末的安全指数吧。
输入格式
从标准输入读入数据。
输入的第一行包含一个正整数 𝑛,保证 2≤𝑛≤105。
接下来输入 𝑛 行,其中第 𝑖(1≤𝑖≤𝑛)行包含用空格分隔的两个整数 𝑤𝑖 和 𝑠𝑐𝑜𝑟𝑒𝑖,分别表示第 𝑖 项指标的重要程度和小菜同学该项的得分。
输出格式
输出到标准输出。
输出一个非负整数 𝑦,表示小菜同学期末的安全指数。
样例输入
6 2 60 10 100 0 70 0 0 -10 50 10 60
输出
1220
代码
#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<string>
using namespace std;
const int N=1e6+100;
typedef long long ll;
typedef pair<int,int>pll;
int n,m,T,a[N];
ll res;
int main()
{
cin>>n;
while(n--)
{
ll a,b;
cin>>a>>b;
res=res+a*b;
}
cout<<max(res,0ll)<<endl;
return 0;
}
期末预测之最佳阈值
题目背景
考虑到安全指数是一个较大范围内的整数、小菜很可能搞不清楚自己是否真的安全,顿顿决定设置一个阈值 𝜃,以便将安全指数 𝑦 转化为一个具体的预测结果——“会挂科”或“不会挂科”。
因为安全指数越高表明小菜同学挂科的可能性越低,所以当 𝑦≥𝜃 时,顿顿会预测小菜这学期很安全、不会挂科;反之若 𝑦<𝜃,顿顿就会劝诫小菜:“你期末要挂科了,勿谓言之不预也。”
那么这个阈值该如何设定呢?顿顿准备从过往中寻找答案。
题目描述
具体来说,顿顿评估了 𝑚 位同学上学期的安全指数,其中第 𝑖(1≤𝑖≤𝑚)位同学的安全指数为 𝑦𝑖,是一个 [0,108] 范围内的整数;同时,该同学上学期的挂科情况记作 𝑟𝑒𝑠𝑢𝑙𝑡𝑖∈0,1,其中 0 表示挂科、1 表示未挂科。
相应地,顿顿用 𝑝𝑟𝑒𝑑𝑖𝑐𝑡𝜃(𝑦) 表示根据阈值 𝜃 将安全指数 𝑦 转化为的具体预测结果。 如果 𝑝𝑟𝑒𝑑𝑖𝑐𝑡𝜃(𝑦𝑗) 与 𝑟𝑒𝑠𝑢𝑙𝑡𝑗 相同,则说明阈值为 𝜃 时顿顿对第 𝑗 位同学是否挂科预测正确;不同则说明预测错误。
最后,顿顿设计了如下公式来计算最佳阈值 𝜃∗
该公式亦可等价地表述为如下规则:
- 最佳阈值仅在 𝑦𝑖 中选取,即与某位同学的安全指数相同;
- 按照该阈值对这 𝑚 位同学上学期的挂科情况进行预测,预测正确的次数最多(即准确率最高);
- 多个阈值均可以达到最高准确率时,选取其中最大的。
输入格式
从标准输入读入数据。
输入的第一行包含一个正整数 𝑚。
接下来输入 𝑚 行,其中第 𝑖(1≤𝑖≤𝑚)行包括用空格分隔的两个整数 𝑦𝑖 和 𝑟𝑒𝑠𝑢𝑙𝑡𝑖,含义如上文所述。
输出格式
输出到标准输出。
输出一个整数,表示最佳阈值 𝜃∗。
样例1输入
6
0 0
1 0
1 1
3 1
5 1
7 1
样例1输出
3
样例1解释
按照规则一,最佳阈值的选取范围为 0,1,3,5,7。
𝜃=0 时,预测正确次数为 4;
𝜃=1 时,预测正确次数为 5;
𝜃=3 时,预测正确次数为 5;
𝜃=5 时,预测正确次数为 4;
𝜃=7 时,预测正确次数为 3。
阈值选取为 1 或 3 时,预测准确率最高; 所以按照规则二,最佳阈值的选取范围缩小为 1,3。
依规则三,𝜃∗=max1,3=3。
样例2输入
8
5 1
5 0
5 0
2 1
3 0
4 0
100000000 1
1 0
样例2输出
100000000
子任务
70 的测试数据保证 𝑚≤200;
全部的测试数据保证 2≤𝑚≤105。
思路
数据范围nlogn的算法,阀值选择y中的数据,理解题意就是,比y大的数,预测结果应该是1,反之是0.
我们需要一个可以快速求出比其中y值大的对应的result有多少个1,比这个值小的有多少个0,我们可以利用前缀和快速求出。
整体思路就是排序,求前缀和,处理。
代码
#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstdio>
#include<string>
#include<set>
using namespace std;
const int N=1e6+100;
typedef long long ll;
typedef pair<int,int>pll;
int n,m,T,a[N];
pll p[N];
int res=-1;
int sum[N];
set<int>st;
int _res;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int a,b;
scanf("%d %d",&a,&b);
p[i]=make_pair(a,b);
}
sort(p+1,p+n+1);
for(int i=1;i<=n;i++) sum[i] =sum[i-1]+ p[i].second;
// for(int i=1;i<=n;i++) cout<<sum[i]<<' ';
// cout<<endl;
for(int i=1;i<=n;i++)
{
int a=p[i].first;
// b=p[i].second;
//int _sum=sum[n] - sum[i-1] + i -sum[i-1] ;
if(st.count(a)) continue;
st.insert(a);
int yuche = sum[n]-sum[i-1] + i-1-sum[i-1];
//cout<<a<<' '<<yuche<<endl;
if(yuche >= res) {
res=yuche;
_res=a;
}
}
cout<<_res;
return 0;
}
星际旅行
线段树的区间加 区间乘 骗分40分,再加上特判n小于1000,用暴力骗20分,一共60分。
剧本都写好了,就是没有想到,评测机不工作,一直waiting。都不敢瞎交骗分了,完事就写了线段树版本的骗分
#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<string>
using namespace std;
const int N=1e5+100,P=1e9+7;
int n,m;
typedef long long ll;
#define int long long
struct node{
int l,r;
ll _sum,_add,_mul;
}tr1[N*4],tr2[N*4],tr3[N*4];
int a[N];
void _mul_add(node &t,int _mul,int _add)
{
t._sum = ((ll)t._sum * _mul + (ll)(t.r - t.l + 1) * _add) % P;
t._mul = (ll)t._mul * _mul % P;
t._add = ((ll)t._add * _mul + _add) % P;
}
void pushup1(int u)
{
tr1[u]._sum=(tr1[u<<1]._sum+tr1[u<<1|1]._sum)%P;
}
void pushup2(int u)
{
tr2[u]._sum=(tr2[u<<1]._sum+tr2[u<<1|1]._sum)%P;
}
void pushup3(int u)
{
tr3[u]._sum=(tr3[u<<1]._sum+tr3[u<<1|1]._sum)%P;
}
void pushdown1(int u)
{
_mul_add(tr1[u<<1],tr1[u]._mul,tr1[u]._add);
_mul_add(tr1[u<<1|1],tr1[u]._mul,tr1[u]._add);
tr1[u]._add=0;
tr1[u]._mul=1;
}
void pushdown2(int u)
{
_mul_add(tr2[u<<1],tr2[u]._mul,tr2[u]._add);
_mul_add(tr2[u<<1|1],tr2[u]._mul,tr2[u]._add);
tr2[u]._add=0;
tr2[u]._mul=1;
}
void pushdown3(int u)
{
_mul_add(tr3[u<<1],tr3[u]._mul,tr3[u]._add);
_mul_add(tr3[u<<1|1],tr3[u]._mul,tr3[u]._add);
tr3[u]._add=0;
tr3[u]._mul=1;
}
void _build_tree(int u,int l,int r)
{
if(l==r)
{
tr1[u]={l,l,a[l],0,1};
tr2[u]={l,l,a[l],0,1};
tr3[u]={l,l,a[l],0,1};
}
else{
tr1[u]={l,r,a[l],0,1};
tr2[u]={l,r,a[l],0,1};
tr3[u]={l,r,a[l],0,1};
int mid=l+r>>1;
_build_tree(u<<1,l,mid);
_build_tree(u<<1|1,mid+1,r);
pushup1(u);
pushup2(u);
pushup3(u);
}
}
void modify1(int u,int l,int r ,int _mul,int _add)
{
if(tr1[u].l>=l && tr1[u].r<=r)
{
_mul_add(tr1[u],_mul,_add);
}
else{
pushdown1(u);
int mid=tr1[u].l+tr1[u].r>>1;
if(l<=mid) modify1(u<<1,l,r,_mul,_add);
if(r>mid) modify1(u<<1|1,l,r,_mul,_add);
pushup1(u);
}
}
void modify2(int u,int l,int r ,int _mul,int _add)
{
if(tr2[u].l>=l && tr2[u].r<=r)
{
_mul_add(tr2[u],_mul,_add);
}
else{
pushdown2(u);
int mid=tr2[u].l+tr2[u].r>>1;
if(l<=mid) modify2(u<<1,l,r,_mul,_add);
if(r>mid) modify2(u<<1|1,l,r,_mul,_add);
pushup2(u);
}
}
void modify3(int u,int l,int r ,int _mul,int _add)
{
if(tr3[u].l>=l && tr3[u].r<=r)
{
_mul_add(tr3[u],_mul,_add);
}
else{
pushdown3(u);
int mid=tr1[u].l+tr1[u].r>>1;
if(l<=mid) modify3(u<<1,l,r,_mul,_add);
if(r>mid) modify3(u<<1|1,l,r,_mul,_add);
pushup3(u);
}
}
ll query1(int u,int l,int r)
{
if(tr1[u].l>=l && tr1[u].r<=r) return tr1[u]._sum;
ll res=0;
pushdown1(u);
int mid=tr1[u].l+tr1[u].r>>1;
if(l<=mid) res+=query1(u<<1,l,r);
if(r>mid) res=(res+query1(u<<1|1,l,r))%P;
return res;
}
ll query2(int u,int l,int r)
{
if(tr2[u].l>=l && tr2[u].r<=r) return tr2[u]._sum;
ll res=0;
pushdown2(u);
int mid=tr2[u].l+tr2[u].r>>1;
if(l<=mid) res+=query2(u<<1,l,r);
if(r>mid) res=(res+query2(u<<1|1,l,r))%P;
return res;
}
ll query3(int u,int l,int r)
{
if(tr3[u].l>=l && tr3[u].r<=r) return tr3[u]._sum;
ll res=0;
pushdown3(u);
int mid=tr3[u].l+tr3[u].r>>1;
if(l<=mid) res+=query3(u<<1,l,r);
if(r>mid) res=(res+query3(u<<1|1,l,r))%P;
return res;
}
signed main()
{
cin>>n>>m;
//scanf("%d%d",&n,&m);
_build_tree(1,1,n);
while(m--)
{
int op;
cin>>op;
//scanf("%d",&op);
if(op==1)
{
int l,r,a,b,c;
cin>>l>>r>>a>>b>>c;
//scanf("%d%d%d%d%d",&l,&r,&a,&b,&c);
modify1(1,l,r,1,a);
modify2(1,l,r,1,b);
modify3(1,l,r,1,c);
}
else if(op==2)
{
int l,r,k;
cin>>l>>r>>k;
//scanf("%d%d%d",&l,&r,&k);
modify1(1,l,r,k,0);
modify2(1,l,r,k,0);
modify3(1,l,r,k,0);
}
else if(op==3){
int l,r;
cin>>l>>r;
//scanf("%d%d",&l,&r);
}
else{
int l,r;
cin>>l>>r;
//scanf("%d%d",&l,&r);
ll res1=query1(1,l,r);
ll res2=query2(1,l,r);
ll res3=query3(1,l,r);
cout<<((res1*res1%P + res2*res2%P)%P+ res3*res3%P)%P<<endl;
}
}
return 0;
}