欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

日志统计 巧用Vector,,map 【蓝桥杯真题】(c++实现)

程序员文章站 2022-07-12 16:47:59
...

上文链接:全球变暖 BFS非递归【蓝桥杯真题】(c++实现)


日志统计

小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:

ts id

表示在ts时刻编号id的帖子收到一个"赞"。

现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。

具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。

给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。

【输入格式】

第一行包含三个整数N、D和K。

以下N行每行一条日志,包含两个整数ts和id。

对于50%的数据,1 <= K <= N <= 1000

对于100%的数据,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000

【输出格式】

按从小到大的顺序输出热帖id。每个id一行。

【输入样例】

7 10 2

0 1

0 10

10 10

10 1

9 1

100 3

100 3

【输出样例】

1

3

资源约定:

峰值内存消耗(含虚拟机) < 256M

CPU消耗 < 1000ms

我的思路

  • 题中可以有两种求解思路,一是根据某个时间段中查找满足大于k的id,记录其数量,二是在某个id对应的时刻中查找在某时间段的点赞数是否大于k,是则记录,两种方式均可。

  • 我讲解比较麻烦的一个:第二个,首先将输入进行预处理,将id进行升序排序,将id对应的时刻进行升序排序,迭代查询某id对应的时刻里(尺取法查询:规定范围查询),在某个时间段是否出现大于k次,是则记录。

  • 注意点,使用结构体或类对id、时刻进行排序时的绑定。

算法展示

第一个对应算法(100%正确):

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
using namespace std;

int N,D,K,ans;

//存储日志 
struct log{
	int id,time;
};
//对id进行升序排序 
bool cmp(log a,log b)
{
	return a.time < b.time;
}


int main()
{
	//快读配置 
	std::ios::sync_with_stdio(0);
	//读取规模 
	cin>>N>>D>>K;
	
	//存储多个日志并排序 
	vector<log> logs(N);
	for(int i = 0;i<N;++i)
	{
		cin>>logs[i].time>>logs[i].id;	
	}
	sort(logs.begin(),logs.end(),cmp);
	
	
	//记录答案 
	set<int> ans;
	//记录id出现的次数
	map<int,int>cnt;
	 
	int j = 0;//哨兵 
	for(int i = 0;i<N;++i)
	{
		while(j<N&&logs[j].time-logs[i].time<D)
		{
			cnt[logs[j].id]++;
			if(cnt[logs[j].id]>=K)ans.insert(logs[j].id);
			j++; 
		}
		cnt[logs[i].id]--;
	}
	
	
	for(set<int>::iterator i = ans.begin();i !=ans.end();i++)cout<<*i<<endl;
	
	return 0;
}

第二个对应算法(67%正确):

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

int N,D,K,ans;

//存储日志 
struct log{
	int id,time;
};
//对id进行升序排序 
bool cmp(log a,log b)
{
	return a.id < b.id;
}


int main()
{
	//快读配置 
	std::ios::sync_with_stdio(0);

	//读取规模 
	cin>>N>>D>>K;
	
	//存储多个日志并排序 
	vector<log> logs(N);
	
	
	for(int i = 0;i<N;i++)
	{
		cin>>logs[i].time>>logs[i].id;	
	}
	
	sort(logs.begin(),logs.end(),cmp);
	set<int> ans; 
	
	int cid,j = 0,end = 0;//当前查找的id,索引j 
	
	while(j<N)//从头开始查找 
	{
		cid = logs[j].id; 
		//查找一组id对应的开始结束日期
		int start = j,end = start,ck = 1;
		while(cid==logs[end].id)end++;
		
		//记录在某时间段中获得赞大于等于K的id 
		for(int si = start;si<end-1;si++)
		{
			for(int ji = si+1;ji<end;ji++)
			{
				if(abs(logs[si].time-logs[ji].time) < D) ck++;
			} 
			if(ck>=K)
			{
				ans.insert(logs[si].id);
				break;	
			}
			ck = 0;
		}
		
		j = end; 
	}	
	
	for(set<int>::iterator i = ans.begin();i !=ans.end();i++)cout<<*i<<endl;
	
	return 0;
}