zoukankan      html  css  js  c++  java
  • PAT甲题题解-1055. The World's Richest (25)-终于遇见一个排序的不水题

    题目简单,但解题的思路需要转换一下,按常规思路肯定超时,推荐~

    题意:给出n个人的姓名、年龄和拥有的钱,然后进行k次查询,输出年龄在[amin,amx]内的前m个最富有的人的信息。
    如果财富值相同就就先输出年龄小的,如果年龄相同就按照名字的字典序排序输出~

    n范围为10^5,所以显然不能每次查询的时候for一遍所有人,把符合条件的选出来再排序输出,这样肯定会超时。

    但是注意到年龄的范围只有200,而且最后查询也跟年龄区间有关,那么有什么办法每次查询我只要取在这个年龄段里的人就好。
    这样就想到用vector数组,vector node[i]存储所有年龄为i的人,且已经从大到小排好序。
    那么对于要找[amin,amax]之间的前m个人,只要每次for一遍node[amin]~node[amax],比较每个node[i]的第一个,找出最大的输出,循环m次即可。
    时间复杂度为k*m*[amax-amin],即O(1000*100*200)

    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int maxn=205;
    struct Node{
        char name[10];
        int age;
        int worth;
    };
    bool cmp(Node a,Node b){
        if(a.worth==b.worth){
            if(a.age==b.age){
                if(strcmp(a.name,b.name)<=0)
                    return true;
                else
                    return false;
            }
            else
                return a.age<b.age;
        }
        else
            return a.worth>b.worth;
    };
    vector<Node> node[maxn]; //索引为年龄,node[i]存储年龄为i的人
    int main()
    {
        int n,k;
        scanf("%d %d",&n,&k);
        Node p;
        for(int i=0;i<n;i++){
            scanf("%s %d %d",p.name,&p.age,&p.worth);
            node[p.age].push_back(p);
        }
        for(int i=1;i<maxn;i++){
            sort(node[i].begin(),node[i].end(),cmp);
        }
        int m,amin,amax;
        int idx[maxn]; //记录每个node[i]参与比较的第一个位置
        int num;
        for(int i=0;i<k;i++){
            scanf("%d %d %d",&m,&amin,&amax);
            Node maxNode;
            maxNode.worth=-10000000;
            num=0;//统计有没有人,没有的话输出None
            int maxid;
            memset(idx,0,sizeof(idx));
            printf("Case #%d:
    ",i+1);
            //因为要找出前m个,所以for循环m次,每次找出当前最大的一个
            for(int j=1;j<=m;j++){
                maxNode.worth=-10000000;
                maxid=-1;
                //在年龄范围内找出最大的,由于已经从大到小排好序,所以每次只要比较每个vector的第一个即可,其中最大的便肯定是范围内最大的
                for(int g=amin;g<=amax;g++){
                    if(idx[g]<node[g].size()){
                        if(cmp(node[g][idx[g]],maxNode)){
                            maxNode.age=node[g][idx[g]].age;
                            maxNode.worth=node[g][idx[g]].worth;
                            strcpy(maxNode.name,node[g][idx[g]].name);
                            maxid=g;
                        }
                    }
                }
                if(maxid==-1)
                    break;
                num++;
                printf("%s %d %d
    ",node[maxid][idx[maxid]].name,node[maxid][idx[maxid]].age,node[maxid][idx[maxid]].worth);
                idx[maxid]++; //找到最大的输出了,所以索引要++,下一次就比较该vector的下一个元素了。
            }
            if(num==0)
                printf("None
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    亨元模式
    模板方法模式
    组合模式
    命令模式
    Android AIDL使用介绍(2)自定义数据类型的传递*
    Android主线程(ActivityThread)源代码分析
    一个简单的死锁代码*
    ABA问题的本质及其解决办法*
    Java 多线程Atomic 与CAS 原理剖析*
    Java并发编程:volatile关键字解析*
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/6522404.html
Copyright © 2011-2022 走看看