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:\n",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\n",node[maxid][idx[maxid]].name,node[maxid][idx[maxid]].age,node[maxid][idx[maxid]].worth); idx[maxid]++; //找到最大的输出了,所以索引要++,下一次就比较该vector的下一个元素了。 } if(num==0) printf("None\n"); } return 0; }