D - Exam Results Gym - 102769E

题目链接
题意:
1:给定一个数n和一个百分比p(%为单位)
2:输入n行,每一行有两个数据,一个是当前人的最高成绩,一个是最低成绩,且只能得这两个成绩中得一个
3:只有大于最高成绩的p%是才算及格
4:问最多有多少人及格

题解:用两个优先队列,一个是所有的人,另一个是不及格的,然后再遍历将每一个最大值转换成小值的时候的有多少人可以及格,最终找那个最大值即可.具体看代码

下面是AC代码:

#include <bits/stdc++.h>
#include<iostream>
using namespace std;
#define int long long
const int N = 5e5 + 10;
struct node
{
    int now;
    int a, b, id;
    bool operator<(const node &A) const
    {
        if(A.now==now) return A.b > b;
        return (A.now > now);//按照now值排序
    }
} f[N];
int vis[N];
priority_queue<node> que;//所有人的优先队列
priority_queue<node> que1;//不及格人数的优先队列
signed main()
{
    int t;
    cin >> t;
    int Case = 0;
    while (t--)
    {
        while(que.size())
            que.pop();
        while(que1.size())
            que1.pop();//记得清空数组
        printf("Case #%lld: ",++Case);
        int n,jgl;
        scanf("%lld%lld", &n, &jgl);
        for(int i=0;i<=n;i++) vis[i]=0;//标记记得清零
        int fs = 0;
        int minn=-1;
        for (int i = 1; i <= n; i++)
        {
            f[i].id = i;
            scanf("%lld%lld", &f[i].a, &f[i].b);
            f[i].a *= 100;
            f[i].b *= 100;
            f[i].now = f[i].a;
            que.push(f[i]);//将所有人的最大值放进这个代码里
        }
        int pp = que.top().now * jgl / 100;//算出初始值的最大值
        int ans = 0;
        for(int i = 1;i<=n;i++)
        {
            if(f[i].now < pp)
                que1.push(f[i]);
            else
                ans++;//算出初始的及格人数
        }
        while(que.size())
        {
            node p = que.top();//取出当前的最大值
            que.pop();
            int fsx = p.now * jgl / 100;//算出分数线
            vis[p.id] ++;//记录使用过的次数,大于两次直接break不然可能某一个人的最小值和最大值都能做最大值,这样就就会死循环
            node nowp = p;
            nowp.now = nowp.b;
            que.push(nowp);//now值变为b后放入队列
            while(que1.size()) //不及格
              {
                node p1 = que1.top();
                if(fsx > p1.now)
                    break;
                que1.pop();//及格的一定要pop掉不能放回原来的que,因为放到原来的que后原来的que就乱了
            }
            ans = max(ans,n - (int)que1.size());//每次找出一个最大值
            if(nowp.now<fsx) que1.push(nowp);//这个一定要放在while循环后面
            if(vis[p.id]>=2) break;//访问超过两次直接break
        }
        cout << ans << endl;
    }
    return 0;
}

下面是AC的第二种写法:(本质上是一样的,具体看代码即可)

#include <bits/stdc++.h>
#include<iostream>
using namespace std;
#define int long long
const int N = 5e5 + 10;
struct node
{
    int now;
    int a, b, id;
    bool operator<(const node &A) const
    {
        if(A.now==now) return A.b > b;
        return (A.now > now);//按照now值排序
    }
} f[N];
int vis[N];
priority_queue<node> que;//所有人的优先队列
priority_queue<node> que1;//不及格人数的优先队列
signed main()
{
    int t;
    cin >> t;
    int Case = 0;
    while (t--)
    {
        while(que.size())
            que.pop();
        while(que1.size())
            que1.pop();//记得清空数组
        printf("Case #%lld: ",++Case);
        int n,jgl;
        scanf("%lld%lld", &n, &jgl);
        for(int i=0;i<=n;i++) vis[i]=0;//标记记得清零
        int fs = 0;
        int minn=-1;
        for (int i = 1; i <= n; i++)
        {
            f[i].id = i;
            scanf("%lld%lld", &f[i].a, &f[i].b);
            f[i].a *= 100;
            f[i].b *= 100;
            f[i].now = f[i].a;
            que.push(f[i]);//将所有人的最大值放进这个代码里
        }
        int pp = que.top().now * jgl / 100;//算出初始值的最大值
        int ans = 0;
        for(int i = 1;i<=n;i++)
        {
            if(f[i].now < pp)
                que1.push(f[i]);
            else
                ans++;//算出初始的及格人数
        }
        //这个整体的思路就是在开始就找交换然后找最小值
        while(que.size())
        {
            node p = que.top();//取出当前的最大值
            que.pop();
            node t1=p;
            t1.now=p.b;
            que.push(t1);
            p=que.top();
            int fsx = p.now * jgl / 100;//算出分数线
            vis[p.id] ++;//记录使用过的次数,大于两次直接break不然可能某一个人的最小值和最大值都能做最大值,这样就就会死循环
            if(t1.now<fsx) que1.push(t1);
            while(que1.size()) //不及格
              {
                node p1 = que1.top();
                if(fsx > p1.now)
                    break;
                que1.pop();//及格的直接出去即可
            }
            ans = max(ans,n - (int)que1.size());//每次找出一个最大值
            if(vis[p.id]>=2) break;//访问超过两次直接break
        }
        cout << ans << endl;
    }
    return 0;
}

这个题改了很长的时间,本来以为是思路问题,后来找到样例后发现是一些细节没有注意到,截个图纪念一下吧:
在这里插入图片描述
下面是WA2的代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e5 + 10;
struct node
{
    int now;
    int a, b, id;
    bool operator<(const node &A) const
    {
        if(A.now==now) return A.b > b;
        return (A.now > now);
    }
} f[N];

int vis[N];
priority_queue<node> que;
priority_queue<node> que1;
signed main()
{
    int t;
    cin >> t;
    int Case = 0;
    while (t--)
    {
        while(que.size())
            que.pop();
        while(que1.size())
            que1.pop();
        printf("Case #%lld: ",++Case);
        int n,jgl;
        scanf("%lld%lld", &n, &jgl);
        for(int i=0;i<=n;i++) vis[i]=0;
        int fs = 0;
        for (int i = 1; i <= n; i++)
        {
            f[i].id = i;
            scanf("%lld%lld", &f[i].a, &f[i].b);
            f[i].a *= 100;
            f[i].b *= 100;
            f[i].now = f[i].a;
            que.push(f[i]);
        }
        int pp = que.top().now * jgl / 100;
        int ans = 0;
        for(int i = 1;i<=n;i++)
        {
            if(f[i].now < pp)
                que1.push(f[i]);
            else
                ans++;
        }
        while(que.size())
        {
            node p = que.top();
            que.pop();
            node nowp = p;
            nowp.now = nowp.b;
            int fsx = p.now * jgl / 100;
            if(nowp.b<fsx) que1.push(nowp);
            else que.push(nowp);
            vis[p.id] ++;
            while(que1.size()) //不及格
              {
                node p1 = que1.top();
                if(fsx > p1.now)
                    break;
                que1.pop();
            }
            ans = max(ans,n - (int)que1.size());
            if(vis[p.id]>=2) break;//访问超过两次直接break
        }
        cout << ans << endl;

    }
    return 0;
}

下面是纠错的样例:
1
5 100
100 2
1 1
2 1
2 1
2 1
答案是:4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值