2018年第九届蓝桥杯C++省赛B组H题

2018年第九届蓝桥杯C++省赛B组H题

日志统计

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

蓝桥杯蓝桥杯我来啦!!

这道题应该算是比较简单的把,我可能对双指针情有独钟,所以又来写他的题解了=-=被双指针打击到了qaq

这道题很直观直接模拟即可。
把时间放入对应id的容器中,然后sort一下。
然后用尺取法的思想找一下有没有符合要求的id即可,
因为我们id本身遍历的时候就是从大到小遍历的,所以直接输出即可。
然后注意一下边界条件就可以啦,要在d的时间范围内,不能包括d,也就是只能小于d

双指针l1, l2走一遍就可以啦,遇到符合条件的break,成功继承zz思想哈哈哈。
这里有个地方就是不需要还原计数,因为根据尺取法的思想嘛,已经产生了固定满足要求的区间了,所以从第一个符合要求的地方开始,后面的全都符合大于d的要求,因为l1和l2都在++嘛。相反如果还原计数为0的话会比较麻烦。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;

vector<int> a[N];
vector<int> ans; 

int main()
{
	int n, d, k;
	int s = 0;
	cin >> n >> d >> k;
	for (int i = 1; i <= n; i++)
	{
		int id, t;
		cin >> t >> id;
		a[id].push_back(t);
		s = max(s, id);
	}
	for (int i = 0; i <= s; i++)
	{
		sort(a[i].begin(), a[i].end());
		int l1 = 0, l2 = 0, r = a[i].size();
		int flag = 0;
		int cnt = 0;
		
		while (l2 < r)
		{
			cnt++;
			if (cnt >= k)
			{
				if (a[i][l2] - a[i][l1] < d)
				{
					flag = 1;
					break;
				}
				else
				{
					l1++;
				}
			}
			l2++;
		}
		if (flag)
		{
			ans.push_back(i);
		}
	}
	int siz = ans.size();
	for (int i = 0; i < siz; i++)
	{
		cout << ans[i] << endl;
	}
	return 0;
}
发布了53 篇原创文章 · 获赞 2 · 访问量 1351

猜你喜欢

转载自blog.csdn.net/qq_44624316/article/details/104564321