3.6 日志统计(双指针优化)
方法一: 暴力求解
测试点情况: 6/15 可以“苟分”
第一次循环:时间从 0 0 0到最大时间
第二层循环:遍历所有的 i d id id,判断是否满足题设条件,是的话统计数组+1,最后判断点赞量是否>= K K K
特别注意:每层循环都要将计数数组置为 0 0 0
代码:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef struct
{
int ts;
int id;
}bk;
bk blog[100010];
int n,d,k;
int cnt[100010]={0}; //存储点赞信息,下标为id,内容为点赞数量
bool hot[100010]={0};//存储是否为热帖
int main()
{
cin>>n>>d>>k;
int maxtime=0; //记录最大时间
for(int i=1;i<=n;i++)
{
cin>>blog[i].ts>>blog[i].id;
maxtime=max(maxtime,blog[i].ts);
}
for(int time=0;time<=maxtime;time++)
{
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)
{
int t=blog[i].ts;
int m=blog[i].id;
if(t>=time&&t<time+d)
cnt[m]++;
if(cnt[m]>=k)
hot[m]=true;
}
}
for(int i=0;i<=100010;i++)
if(hot[i]) cout<<i<<endl;
return 0;
}
方法二:双指针优化
思考:
因为要用到双指针,所以要按照时间对结构体进行排序
i , j i,j i,j 是两个记录位置的指针, i i i 在 j j j 的前面向前移动,对排好序的时间进行遍历, j j j 留在 i i i 的后面帮他看着,因为时间是排好顺序的,所以只要 i i i 向前找到一个位置对应的时间和 j j j 对应的时间之差超过了题目要求的 D D D,那么 j j j 就要向前移动,直到找到一个位他们的时间之差再次满足 D D D
理解,如图:
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define ts first
#define id second
typedef pair<int,int> bg;
bg blog[100010];
int n,d,k;
int cnt[100010]={0}; //存储点赞信息,下标为id,内容为点赞数量
bool hot[100010]={0};//存储是否为热帖
int main()
{
cin>>n>>d>>k;
for(int i=0;i<n;i++) cin>>blog[i].ts>>blog[i].id;
sort(blog,blog+n);
for(int i = 0,j = 0; i < n;i++)
{
int b = blog[i].id;
cnt[b]++;
while(blog[i].ts - blog[].ts >= d)
{
cnt[blog[j].id]--;
j++;
}
if(cnt[b] >= k) hot[b] = true;
}
for(int i=0;i<=100000;i++)
if(hot[i]) cout<<i<<endl;
return 0;
}