题目地址
Decode Registration Card of PAT (25分)
题目大意
这是一道模拟数据库查询的题目,样例给出了由考号和分数组成的数据信息。然后告诉了考号是由一位考试等级,三位考场编号、六位考试日期和三位考生号组成。我们需要实现三种查询数据的要求:
- 查询类型1:根据考试等级查询,输出查询的考试等级的所有考生信息,输出形式是考号 成绩,并按照成绩降序排列,当成绩相同时,按照考号字符串大小升序排列,考号唯一。
- 查询类型2:根据考场查找,输出查找考场的考生人数以及他们的总分数。
- 查找类型3:根据考试日期查找,输出对应日期的考场号以及每个考场的人数,数据按照人数降序排列,当考场人数相同时按照考场号升序排列,考场号唯一。
解题思路
题目看似难度不大,但在解题中不注意细节很容易算法超时,或者陷入某些测试点错误需要花大量时间排查。
- 如果使用串操作,输入输出方式频繁采用cin和cout,在检索时也用串进行比较很容易超时(最后2个测试点)。可以将考号划分后转为int和char类型存放,比较和输出会节约很多的时间。
- 如果采用串输入输出不需要头部补0,如果用int型注意格式!
- 查询类型1用sort排序就可以解决;查询类型2定义求和变量,求和筛选后的数据也容易得到结果。主要是查询类型3的设计方式会影响运行时间。
- 查询类型3我用的是hash加上一个vector,时间复杂度和类型2差不多。我一开始采用vector,outnode{int sizeid,int sum}的存储模式需要在进行一次循环查找,就超时啦。真的可以用hash还是用hash比较好,空间基本不会超的。
测试点排查
前3个测试点包含的数据量比较小不会超时,后2个测试点会出现超时的情况,具体每个测试点包含的范围:
- 每个测试点都包含查询类型1
- 测试点0 就是样例给出的
- 测试点2 只包含查询类型1
- 测试点3 主要考察查询类型 3在数据量较大时是否超时,并且测试点3不包含查询类型2
- 测试点4 考察查询类型1在数据量较大是否超时,包含部分查询类型2和查询类型3
完整代码
// A1153.cpp : Defines the entry point for the console application.
//
#include "stdio.h"
#include "string"
#include "vector"
#include "iostream"
#include "algorithm"
using namespace std;
struct node{
string all;
char first;
int second,third,score;
};
int n,k;
vector<node> haha;
vector<node> da;
int hsh[11100];
vector<int> ans;
void add(string a,int x){
node p;
p.score = x;
p.all = a;
p.first = a[0];
p.second = (a[1]-'0')*100+(a[2]-'0')*10+(a[3]-'0');
p.third = (a[4]-'0')*100000+(a[5]-'0')*10000+(a[6]-'0')*1000+(a[7]-'0')*100+(a[8]-'0')*10+a[9]-'0';
//p.f = (a[10]-'0')*100+(a[11]-'0')*10+a[12]-'0';
//cout<<p.first<<p.second<<p.third<<p.f<<endl;
haha.push_back(p);
}
bool cmp(node a,node b){
if(a.score == b.score) return a.all < b.all;
return a.score > b.score;
}
bool cmp1(int a,int b){
if(hsh[a] == hsh[b]) return a < b;
return hsh[a] > hsh[b];
}
void print(int typ){
int i,sum = 0;
if(typ == 2){
for(i = 0;i < da.size();i++)
sum += da[i].score;
printf("%d %d\n",da.size(),sum);
}
if(typ == 3){
ans.clear();
fill(hsh,hsh+11100,0);
for(i = 0;i < da.size();i++){
if(hsh[da[i].second] == 0) ans.push_back(da[i].second);
hsh[da[i].second] += 1;
}
sort(ans.begin(),ans.end(),cmp1);
for(i = 0;i < ans.size();i++)
printf("%03d %d\n",ans[i],hsh[ans[i]]);
}
}
int main(int argc, char* argv[])
{
int i = 1,flag = 0;
scanf("%d %d",&n,&k);
while(n--){
int u;
string t;
cin>>t>>u;
add(t,u);
}
sort(haha.begin(),haha.end(),cmp);
while(i <= k){
flag = 0;
da.clear();
int u,t,v;//u = 1 考级,= 2考场, = 3 日期
char z = 0;
scanf("%d",&u);
printf("Case %d: ",i);
if(u == 1){
while(z != 'A' && z != 'T' && z!= 'B')
scanf("%c",&z);
printf("%d %c\n",u,z);
}else{
scanf("%d",&v);
if(u == 3)
printf("%d %06d\n",u,v);
else
printf("%d %03d\n",u,v);
}
for(t =0;t < haha.size();t++){
node p = haha[t];
if(u == 1){
if(p.all[0] == z){
cout<<p.all;
printf(" %d\n",p.score);
flag = 1;
}
}else if(u == 2){
if(p.second == v) da.push_back(p);
}else{
if(p.third == v) da.push_back(p);
}
}
if(da.size() > 0){
print(u);
}else if(flag != 1){
printf("NA\n");
}
i++;
}
//printf("Hello World!\n");
return 0;
}
总结
用STL和sort就可以解决,难度一般主要是一些细节问题,相对板子题稍难,需要注意输入输出格式。
- 欢迎评论区交流讨论。