P8661 [蓝桥杯 2018 省 B] 日志统计
题目传送门:P8661 [蓝桥杯 2018 省 B] 日志统计
提供一个与其他题解都不同的做法。
思路:
先把输入的日志先按编号从小到大排序,编号相同再按时间从小到大排序。
在排过序的结构体中,从 \(1\) 到 \(n\) 枚举区间右端点 \(r\),以帖子曾经是“热帖”的最小区间长度(最小点赞数)\(k\) 确定区间左端点 \(l=r-k+1\),判断几种情况:
- 若 \(l<1\),则不存在该区间,该区间非法;
- 若 \(l\) 所属帖子的编号与 \(r\) 所属帖子的编号不同,该区间非法;
- 若 \(l\) 所属帖子的点赞时间与 \(r\) 所属帖子的点赞时间相差不小于 \(d\)(大于等于 \(d\)),该区间非法;
- 若这个帖子已经被评为热帖(这个帖子的编号被输出过),该区间非法。
若这个区间以上任何一个条件都不满足,则这个区间合法,输出这个帖子的编号(\(r\) 所属帖子的编号)。
同时,这种输出方法也满足按从小到大的顺序输出热帖 \(id\)。
Code:
无注释
有注释
#include<bits/stdc++.h>
using namespace std;
int n,d,k;//题意
struct node { int t,id; } a[1<<20]; //结构体存
bool cmp(node x,node y) { return x.id<y.id||(x.id==y.id&&x.t<y.t); }
//对结构体 node 进行排序:
//先按编号从小到大排序,编号相同再按时间从小到大排序
bool vis[1<<20]; //记录编号是否输出过
signed main()
{
cin>>n>>d>>k; //输入
for(int i=1;i<=n;i++) cin>>a[i].t>>a[i].id; //输入
sort(a+1,a+1+n,cmp);//排序
for(int i=1;i<=n;i++)//枚举右端点
{
int l=i-k+1,r=i;
//枚举区间 [l(i-k+1),r(i)],保证此区间点赞数恒为 k
if(l<1) continue;
//如果 l 不合法(比一小),开始下一次循环
if(a[l].id!=a[r].id) continue;
//如果 l 与 r 所属帖子 id 不同,此区间不合法,开始下一次循环
if(a[r].t-a[l].t>=d) continue;
//如果两次点赞时间间隔 >= d,此区间不合法,开始下一次循环
if(vis[a[l].id]) continue;
//如果这个 id 被记录过(被输出过),开始下一次循环
//合法情况
cout<<a[l].id<<endl; //输出
vis[a[l].id]=1; //记录
}
return 0;
}
以下是博客签名,正文无关
本文来自博客园,作者:Wy_x,转载请在文首注明原文链接:https://www.cnblogs.com/Wy-x/articles/18704577
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC-BY-NC-SA 4.0 协议)进行许可。

浙公网安备 33010602011771号