题目链接
思路
这道题在L2里属于偏简单的一道,数据范围很友好,倾向于使用逻辑而非算法.但想要比较轻松的完成这道题目还是需要一些stl使用经验的.
对于一个用户,有几个需要记录的属性:
- 姓名,用于输出
- 总点赞数,用于确定输入标签的数量,以及确定输出顺序的次要因素
- 点赞的标签总数,确定输出顺序的主要因素
- 点赞过的标签数,用于去重.
实现过程
对于一个用户的属性,用一个结构体可以轻松容纳;
姓名和点赞数输入都会给出,存下来就行;
在输入用户点赞的标签时,边判重边累加其点赞过的标签总数即可.
判重我使用了set,根据其唯一性判断标签是否存在过,未存在过答案+1.将其标记为存在(插入set中).标签友好的数据范围也可以用bool数组来判断,记得每次重新声明或者memset就行.
在全部输入和计算完成后,用sort加上自己写的cmp函数排序即可.
排序优先按照点赞标签数从高到低,同标签数按点赞次数从小到大排序就行(题目那描述我有点没看懂…),顺序别反了.
输出前还要判断下n是否小于三个,如果小于空位要补上-.还要注意行尾不能有多余空格的输出格式.
代码实现
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
struct Node//存用户的结构体
{
string name;//用户名
int num;//用户点赞总数
set<int> tag;//用户点赞过的标签
int ans = 0;//用户点赞过的标签数
} user[N];
bool cmp( Node a,Node b )//自定义排序函数
{
if ( a.ans != b.ans )//优先按照点赞标签数从大到小排序
return a.ans > b.ans;
else//其次按照点赞数量从小到大排序
return a.num < b.num;
}
int main()
{
int n;
cin >> n;//用户数量
for ( int i = 0 ; i < n ; i++ )
{
cin >> user[i].name >> user[i].num;
for ( int j = 0 ; j < user[i].num ; j++ )//遍历用户输入的标签
{
int k;//临时存放标签
cin >> k;
if ( !user[i].tag.count(k))//没出现过
{
user[i].tag.insert(k);//加入到出现过的标签中
user[i].ans++;//用户点赞过的标签+1
}
}
}
sort(user,user + n,cmp);//排序
int i;//存输出次数
for ( i = 0 ; i < n && i < 3 ; i++ )//输出时同时判断n<3情况
{
if ( i )
cout << ' ';
cout << user[i].name;
}
while ( i++ < 3 )//已经输出完了就输出-补位
{
if ( i )
cout << ' ';
cout << '-';
}
return 0;
}