第四章 排序 1 AcWing 1484. 最佳排名

第四章 排序 1 AcWing 1484. 最佳排名

我的思路

模拟, 进行四次排序, 依据优先级取排名最优排名及学科

算法

快排 暴力枚举

Time Limit Exceeded

数据 4/10

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define x first
#define y second
#define ump unordered_map
#define pq priority_queue
#define rep(i, a, b) for(int i=a;i<b;++i)
#define Rep(i, a, b) for(int i=a;i>b;--i)
using namespace std;
typedef pair<int, int> PII;
const int N=2005;
//int t, n, m, cnt, ans; 
int n,m;
inline int rd(){
  int s=0,w=1;
  char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
  while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
  return s*w;
}
void put(int x) {
    if(x<0) putchar('-'),x=-x;
    if(x>=10) put(x/10);
    putchar(x%10^48);
}
struct Stu{
    string id;
    int a, b, c, d;
}stu[N];
bool cmpA(Stu A, Stu B){
    return A.a>B.a;
}
bool cmpB(Stu A, Stu B){
    return A.b>B.b;
}
bool cmpC(Stu A, Stu B){
    return A.c>B.c;
}
bool cmpD(Stu A, Stu B){
    return A.d>B.d;
}


signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	rep(i, 0, n){
	    cin>>stu[i].id>>stu[i].a>>stu[i].b>>stu[i].c;
	    stu[i].d=(stu[i].a+stu[i].b+stu[i].c)/3.+0.5;
	}
	while(m--){
	    string ID;
	    cin>>ID;
	    int mn=2005;
	    char c;
	    sort(stu, stu+n, cmpC);
	    rep(i, 0, n){
	        if(stu[i].id==ID){
	            int t=stu[i].c;
	            while(i&&t==stu[i-1].c){
	                i-=1;
	            }
	            if(i<=mn){
	                mn=i;
	                c='E';
	            }
	            break;
	        }
	    }
	    sort(stu, stu+n, cmpB);
	    rep(i, 0, n){
	        if(stu[i].id==ID){
	            int t=stu[i].b;
	            while(i&&t==stu[i-1].b){
	                i-=1;
	            }
	            if(i<=mn){
	                mn=i;
	                c='M';
	            }
	            break;
	        }
	    }
	    sort(stu, stu+n, cmpA);
	    rep(i, 0, n){
	        if(stu[i].id==ID){
	            int t=stu[i].a;
	            while(i&&t==stu[i-1].a){
	                i-=1;
	            }
	            if(i<=mn){
	                mn=i;
	                c='C';
	            }
	            break;
	        }
	    }
	    sort(stu, stu+n, cmpD);
	    rep(i, 0, n){
	        if(stu[i].id==ID){
	            int t=stu[i].d;
	            while(i&&t==stu[i-1].d){
	                i-=1;
	            }
	            if(i<=mn){
	                mn=i;
	                c='A';
	            }
	            break;
	        }
	    }
	    if(mn!=2005){
	        cout<<mn+1<<" "<<c<<"\n";
	    }else{
	        cout<<"N/A"<<"\n";
	    }
	 
	}
	return 0;
}

正解

思路

将每名学生存储成一个 map 映射,键为 id 对应值为其四门成绩, vector类型的
vector grades[4] 则存储四门课程所有的学生的单门课程成绩并排序
对于每一个查询,先看 map 中是否存在该名学生,如存在分别计算出每门课程的成绩,取排名最高的一个, 对已排序的成绩二分得到对应排名

算法标签

排序 二分

AC代码

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define x first
#define y second
#define ump unordered_map
#define pq priority_queue
#define pii pair<int, int>
#define rep(i, a, b) for(int i=a; i<b; ++i)
#define Rep(i, a, b) for(int i=a; i>=b; --i)
#define debug(a) cout<<#a<<"="<<a<<endl;
#define debugi(i) printf("i = %lld\n", i)
const int N=10005;
int n, m;
ump<string, vector<int>> gra;
vector<int> q[4];
inline int rd(){
    int s=0, w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-'){
            w=-1;    
        }
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=s*10+ch-'0';
        ch=getchar();
    }
    return s*w;
}
int get_r(vector<int> &a, int x){
    int l=0, r=a.size()-1;
    while(l<r){
    // 如果 mid 下取整,在区间只有 2 22​ 个数的时候有 mid 的值等于 left,一旦进入分支 [mid..right] 区间不会再缩小,出现死循环。把取中间数的方式改成上取整。即l+r+1      
    	int mid=l+r+1>>1;
    	// 获取第一次出现对应下标
        if(a[mid]<=x){
            l=mid;
        }else{
            r=mid-1;
        }
    }
    return a.size()-r;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    // n=rd(), m=rd();
    cin>>n>>m;
    rep(i, 0, n){
        string id;
        cin>>id;
        int t[4]={0};
        rep(j, 1, 4){
            cin>>t[j];
            t[0]+=t[j];
        }
        t[0]=round(t[0]/3.0);
        rep(j, 0, 4){
            q[j].push_back(t[j]);
            gra[id].push_back(t[j]);
        }
    }
    rep(i, 0, 4){
        sort(q[i].begin(), q[i].end());
    }
    char names[]="ACME";
    while(m--){
        string id;
        cin>>id;
        if(gra.count(id)==0){
            cout<<"N/A\n";
        }
        else{
            int res=n+1;
            char c;
            rep(i, 0, 4){
                int r=get_r(q[i], gra[id][i]);
                if(r<res){
                    res=r;
                    c=names[i];
                }
            }
            cout<<res<<' '<<c<<"\n";
        }
    }
    return 0;
}

参考文献
AcWing 1477. 拼写正确(PAT甲级辅导课)y总视频讲解

原创不易
转载请标明出处
如果对你有所帮助 别忘啦点赞支持哈
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞滕人生TYF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值