蓝桥杯2018省赛C++B组---日志统计

207 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

题目描述

小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有NN行。其中每一行的格式是:

tsts idid

表示在 tsts 时刻编号 idid 的帖子收到一个"赞"。

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

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

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

输入描述

输入格式:

第一行包含三个整数 NN,DD,KK

以下 NN 行每行一条日志,包含两个整数 tstsidid。 其中,1KN1051≤K≤N≤10^50ts1050≤ts≤10^5,0id1050≤id≤10^5

输出描述

按从小到大的顺序输出热帖 idid。每个 idid 一行

输入输出样例

示例

输入

7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3

输出

1 
3

看到这道题我们第一想法是枚举长度DD个区间,挨个判断里面的idid是否满足点赞数量K≥K,但是很显然,这样做的时间复杂度是O(T2)O(T^2),会超时,所以我们要考虑优化,我们注意到输入是乱序的,因此我们应该想到先对tsts进行排序,因此开一个结构体,存时间tsts和序号idid,先按照tsts从小到大的顺序排序,从第一个时间段开始遍历。 我们注意到因为是连续时间段,所以我们可以维护一个区间(即[T,T+D)[T,T+D)  ),及时更新区间里面的idid和这个idid所对应赞的数量,如果数量K≥K,那就将这个idid存入一个数组ansans,最后跑完nn条日志,将ansans排序,输出。

由以上步骤我们可以知道,遍历可以做到单调,就是不走回头路,我们可以通过双指针算法来实现,我们可以用mapmap来维护这个区间。 贴上代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string> 
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack> 
#include <cmath>
#include <iomanip>
#define ll long long
#define AC return
#define Please 0
using namespace std;
const int N=100010;
const double eps=1e-9;
typedef pair<int,int>PII;
typedef unsigned long long ull; 
int n,d,k;
bool flag[N];//判断id是否出现过
inline int read(){//快读 
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9'){
        x=x*10+ch-'0'; 
        ch=getchar();
    }
    AC x*f;
}
int ans[N],cnt=0;
struct mes{
    int ts,id;
}a[N];
bool cmp(mes x,mes y){//排序函数
    return x.ts<y.ts;
    if(x.ts==y.ts){
        return x.id<=y.id;
    }
}
int main(){
    n=read(),d=read(),k=read();//n评论 d时间范围 k条点赞
    for(int i=1;i<=n;i++){
        cin>>a[i].ts>>a[i].id;
    } 
    memset(flag,0,sizeof flag);
    sort(a+1,a+n+1,cmp);
    map<int,int>mp;
    mp.clear();
    for(int j=1,i=1;j<=n;j++){
        while(a[j].ts-a[i].ts>=d){//这里一定要注意,先判断是否大于等于d
                                 //否则可能会出现多加1的情况
            mp[a[i].id]-=1;
            if(mp[a[i].id]==0){
                mp.erase(a[i].id);
            }
            i++;
        }
        mp[a[j].id]+=1;
        if(mp[a[j].id]>=k && flag[a[j].id]==0){
            ans[++cnt]=a[j].id;
            flag[a[j].id]=1;
        }
        
    }
    sort(ans+1,ans+cnt+1);
    for(int i=1;i<=cnt;i++){
        cout<<ans[i]<<endl;
    }
    AC Please;
}

希望能帮到大家(QAQQAQ