AcWing 1238. 日志统计 解题思路及代码

在写之前先发发牢骚(),不想看可以跳过一下,我把csdn当日记本()。讲道理我一个月没更新了,那为啥不更新呢?是我没写题吗?不是,有些,只不过我习惯一个专题刷差不多了再去写csdn,然后。。。。线段树和树状数组现在都还没写完,所以先往后跳了,加上逆天课内排课(指三门数学)根本没啥时间写算法,所以一直拖着,还好最近蓝桥杯马上要比赛了,我也是直接课内放弃了,先把基础学了。不然这300不如吃顿火锅。之后应该会回复更新吧(大概),也有可能考完蓝桥杯就期末月彻底死亡了。得,看题吧。

先贴个题目:

 以及原题链接:1238. 日志统计 - AcWing题库icon-default.png?t=N7T8https://www.acwing.com/problem/content/1240/

然后讲讲思路 ,这题刚开始觉得直接前缀和就好了,然后开了个1e5*1e5的数组,毫不意外的爆了,于是思考怎么办,第一个优化思路是只开一个一维数组存时间节点内的点赞情况,而所有没点赞的情况统一放到有点赞的时候处理,这个思路借鉴AcWing 1241. 外卖店优先级 解题思路及代码-CSDN博客这个题目的思路,然后我们可以发现,这题还不用思考中间经过了多少时间去做减法,只需要确定时间终点T,看有没有点赞记录在T-D之外的,把他删除就好,所以就类似一个滑动窗口,随着时间段终点(拿起点处理也可以)的推移,不断有新的点赞记录进来,也不断有旧的点赞记录被删除。然后这就是全部思路,来看看代码。

#include <iostream>
#include <algorithm>
#define ts first
#define id second
using namespace std;

const int N = 1e5 + 10;

pair<int, int> d[N];
int cnt[N];
bool yx[N];

int main()
{
    int n, D, k;
    cin >> n >> D >> k;
    for (int i = 0; i < n; ++i)
        scanf("%d%d", &d[i].ts, &d[i].id);
    sort(d, d + n);
    for (int i = 0, j = 0; i < n; ++i)
    {
        cnt[d[i].id]++;
        while (d[i].ts - d[j].ts >= D)
        {
            cnt[d[j].id]--;
            j++;
        }
        if (cnt[d[i].id] >= k)
        {
            yx[d[i].id] = true;
        }
    }
    int ans = 0;
    for (int i = 0; i < N; ++i)
        if (yx[i])
            cout << i << endl;
    return 0;
}

注意这个while,有可能在这次处理点赞记录时,有不止一个点赞记录需要被删除。这是一个双指针算法,可以理解成i在前面推移,j在后面追(每次追到能进入到时间段为止)。然后注意可以写一个pair存点赞记录,然后需要根据时间顺序排序处理,不然没法保证时间是按顺序被处理的。

by————2024.4.6刷题记录

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值