洛谷 P8661 [蓝桥杯 2018 省 B] 日志统计

小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有 N N N 行。其中每一行的格式是 ts id,表示在 t s ts ts 时刻编号 i d id id 的帖子收到一个"赞"。

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

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

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

分析

可以先将每个帖子的获赞信息分别存起来,对于每个帖子用单调队列在时间数组上维护一个大小为 d + 1 d+1 d+1 的窗口[1](#1),每次检查队列的大小是否大于 k k k 即可。

注意需要给每个帖子的获赞信息按时间排序。

代码

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 5;
int n, d, k, maxnt = -1e9, maxn = -1e9;
int head, tail, q[N * 10];
vector <int> nbr[N];

bool check(int num){
	for(int x : nbr[num]){
		q[++ tail] = x;
		while(head <= tail && q[tail] - q[head] + 1 >= d + 1){
			head ++;
		}
		if(tail - head + 1 >= k){
			return true;
		}
	}
	return false;
}

int main(){
	cin >> n >> d >> k;
	for(int i = 1, ts, id; i <= n; i ++){
		cin >> ts >> id;
		maxn = max(maxn, id);
		maxnt = max(maxnt, ts);
		nbr[id].push_back(ts);
	}
	for(int i = 1; i <= maxn; i ++){
		sort(nbr[i].begin(), nbr[i].end());
	}
	for(int i = 0; i <= maxn; i ++){
		head = 1, tail = 0;
		if(check(i)){
			cout << i << "\n";
		}
	}
	return 0;
}

  1. 这里窗口的概念跟单调队列模板滑动窗口中的概念一致 ↩︎
相关推荐
会编程的小孩5 小时前
C++ qt的安装
c++
企业数字化笔记7 小时前
视频人体姿态怎么做三维可视化?2D关键点、深度局限与技术选型
人工智能·算法·音视频
?abc!8 小时前
(数组)581. 最短无序连续子数组
数据结构·算法·leetcode
小成2023032026510 小时前
C++~07补充
开发语言·c++
小郎君65810 小时前
MPTT树复选框的半选状态:一棵百万节点树从递归到计数器,再到区间覆盖
算法
酌沧10 小时前
MemT让记忆成为模型内生能力
jvm·人工智能·算法
hold?fish:palm10 小时前
40 二叉树的直径
c++·leetcode
Shimeri11 小时前
越卷越像:我用遗传算法做了个"内卷"实验
算法·three.js·数据可视化·遗传算法·进化算法
解决小子11 小时前
【虚幻引擎】【C++】【GAS框架】构建角色基类、属性集、数值钳制
c++·笔记·游戏引擎·虚幻·gas·能力系统
Evand J11 小时前
【PMSM例程1】永磁同步电机(PMSM)转速与转子电角度观测算法|基于扩展卡尔曼滤波(EKF)的传感器状态估计与误差。附下载链接
算法·电机·1024程序员节·卡尔曼滤波