P13857 [SWERC 2020] Gratitude

题意

给定两个变量 \(N\)\(K\) ,输入 \(3N\) 件事,求前 \(K\) 个最频繁干的事

重点:如果两个字符串一样多,则按下标 \(i\) 来排序。


思路

我们先思考保存字符串数量的问题,这时候就要用到 map 来保存,但我借助了一点哈希的思路,把字符串转换成了 \(id\) ,但要再开一个数组 \(w_i\) 来保存每个 \(id\) 表示的字符串(好像有点麻烦)

接下来保存成数组的字符串数量排序一遍(要用结构体保存数量,第几个和第一次出现时第几个)

最后扫一遍,输出前 \(k\)\(w_{id}\) 就A了( \(id\) 为排序后的 \(a_i\) 里的 \(p\) )


代码

#include <bits/stdc++.h>
using namespace std;
const int N=100000;
map<string,int>mp;;;;           //记录s的个数,也就是每个事件的次数 
int cnt=0;
string w[N];                    //记录下标为i时字符串(事件)是什么 
struct node
{
	int x=0,id,p;               //字符串个数,实际第几个,第一次第几个出现 
}a[N];
int s_id(string s)              //字符串转id 
{
	if (!mp[s]) mp[s]=(++cnt);  //如果有出现过 
	return mp[s];
}
bool cmp(node x,node y)         //排序 
{
	if (x.x!=y.x) return x.x>y.x;
	return x.id>y.id;
}
int main()
{
	int n,k;
	cin >>n>>k;
	string s;
	getline(cin,s);            //抵掉开始的换行 
	for (int i=1;i<=3*n;i++)
	{
		getline(cin,s);
//		cout <<s<<endl;
		int pos=s_id(s);      //转id 
//		cout <<pos<<" ";
		a[pos].x++,a[pos].id=i,a[pos].p=pos,w[pos]=s;   //赋值 
	}
//	for (int i=1;i<=cnt;i++) cout <<a[i].x<<" ";
	sort(a+1,a+cnt+1,cmp);   //排序 
//	cout <<cnt<<endl;
	for (int i=1;i<=k;i++) cout <<w[a[i].p]<<endl;     //最后输出保存的前k个字符串 
	return 0; 
}
 

俺的第一篇题解,求过

posted @ 2026-03-01 15:04  CJRcn  阅读(5)  评论(0)    收藏  举报