日志统计---第九届蓝桥杯省赛题目八

  • 题目描述

    标题:日志统计

小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有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 <= 100,000 
        0 <= ts <= 100,000 
        0 <= id <= 100,000  

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

【输入样例】
  7 10 2
  0 1
  0 10
  10 10
  10 1
  9 1
  100 3
  100 3

【输出样例】
  1  
  3  


资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

注意:
main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include <xxx>
不能通过工程设置而省略常用头文件。

提交程序时,注意选择所期望的语言类型和编译器类型。

  • 解题代码

 //日志统计
 #include<iostream>
 #include<cstdio>
 #include<vector>
 #include<set> 
 #include<algorithm>
 using namespace std;
 
 vector<int> tiezi[100005];
 set<int> id_set;
 //行数、时间间隔、点赞阈值 
 int num, time_Gap, threshold;
 
 bool judge(int id){
 	//预先筛一波点赞数量少的。 
	 if(tiezi[id].size() < threshold){
	 	return false;
	 }
	 
	 //给当前id中的所有时间点进行快速排序。 
	 sort(tiezi[id].begin(), tiezi[id].end());//注意sort函数的用法。 
	 
	 //运用【尺取法】逐段判断是否满足阈值。有点像一个滑动窗口。
	 int begin = 0;
	 int end = begin + threshold-1;
	 while(end < tiezi[id].size()){
	 	if(tiezi[id][end]-tiezi[id][begin] < time_Gap){
	 		//足够点赞数的时间间隔小于设定的时间间隔。满足条件。
			 return true; 
	 	}
	 	end++;
	 	begin++;
	 }
	 return false;
 }
 
 int main()
 {
 	//输入行数、时间间隔、点赞阈值
	 scanf("%d%d%d", &num, &time_Gap, &threshold);
	 for(int i = 0; i < num; i++){
	 	int time, id;
	 	scanf("%d%d", &time, &id);
	 	tiezi[id].push_back(time);
	 	id_set.insert(id);//插入后自动排了序。 
	 }
	 
	 //迭代每一个id。判断该id在限定时间间隔内对应的时刻数量是否满足阈值。
	 set<int>::iterator it;//定义用来遍历set的迭代器。
	 for(it = id_set.begin(); it != id_set.end(); it++){
	 	int id = *it;//获取id。 
		if(judge(id)){//调用judge函数判断该id是否满足条件 。 
			cout<<id<<endl; 
		} 
	 } 
	 
	 return 0;
 }
  • 思路总结

    使用vector<int>类型的数组存放帖子的发布时间,数组的下标代表了帖子的id。这样一个帖子对应一个vector向量。可以通过vector.push_back()函数把当前id对应的发布时刻追加进这个vector向量。必要时刻对vector向量进行快速排序。sort(vector.begin(), vector.end())。

    使用set<int>集合来存放帖子的id。好处是,set是一个有序集合,使用insert()函数把id追加进set后,set会自动排序,且保证集合元素的唯一性。

    最后通过滑动窗口的方法来判断是否符合条件。这一条件是【在限定时间段内是否有足够多的点赞数】。在本解题思路中,博主使用的方法是:做一个判断---判断足够点赞数的时间间隔是否小于规定的时间间隔。使用这个判断有个好处,那就是我们可以直接确定【足够点赞数的时间间隔】。因为vector中元素的数量就是点赞数量,使用begin--end构成的滑动窗口扫描vector中的元素序列,便可解决我们的问题。

  • 经验总结

    1. set可以自动排序。 可以使用set集合来存放id。 

    2. sort(),快速排序函数。

     头文件:#include<algorithm>
     对于数组a[n], sort的使用方法为:sort(a, a+n);
     对于vector<int> a, sort的使用方法为:sort(a.begin(), a.end()); 

    3.使用迭代器遍历set。
   

set<int>::iterator it;//定义用来遍历set的迭代器。
for(it = id_set.begin(); it != id_set.end(); it++){
    int id = *it;//获取id。 
    //id就是从set中拿到的元素了。
} 

//在python中迭代尤为简单┏ (゜ω゜)=☞
for item in list:
   //item就是从list中拿到的元素了。

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值