AcWing 1238. 日志统计
原题链接
中等
作者:
大海呀大海
,
2020-07-10 20:17:11
,
所有人可见
,
阅读 9881
双指针算法
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int, int> PII;
#define x first
#define y second
const int N = 100010;
int n, d, k;
PII logs[N];
bool st[N];//用来标记id号,因为id <= 1e5,所以可以利用遍历来输出。
int cnt[N];//用来记录一个id号获得的赞数,表示形式为cnt[id]++;
int main(){
scanf("%d%d%d", &n, &d, &k);
for (int i = 0; i < n; i ++ ) scanf("%d%d", &logs[i].x, &logs[i].y);
//排序时默认以first为准排序
sort(logs, logs + n);
//双指针算法, i走在前面,j走在后面
for (int i = 0, j = 0; i < n; i ++ ){
int t = logs[i].y;//t表示为i时刻的id号
cnt[t] ++;//在j时刻,id号为t的大佬日记获得了一个赞,给t大佬加一分
while (logs[i].x - logs[j].x >= d){//两个指针跨越的时间超过了d,早期的赞过期了
cnt[logs[j].y] --;//就是这位大佬,获赞的时间太久远了,赞作废了,哭去吧
j ++;//在logs[j].x时刻的太久远了,往前挪挪。
//这个循环,直到最后一个赞不过期为止。
}
//记录热帖的id号,好知道谁才是大佬
if (cnt[t] >= k) st[t] = true;
}
//遍历一遍id号,展现大佬
for (int i = 0; i <= 100000; i ++ ) if (st[i]) cout << i << endl;
return 0;
}
有趣的刷题生活从看到这篇有趣的题解开始~
这里的i时刻和j时刻应该不是准确的说法 思路是利用i和j遍历日志,因为时间是从小到大排序的,所以让j从头开始,不断遍历i下标的日志,如果j和i指向的时间差大于D了就让j移动直到满足时间差的关系,而移动j势必有日志要移出区间,于是先删再移 这里可以思考一下while循环和最后if判断的顺序问题 可以帮助更好的理解过程
while (logs[i].x - logs[j].x >= d)我不理解他是怎么确定 i 和 j 的id相同
i和j的id不需要相同。你首先得知道他是如何枚举的。它是枚举每个时间段,在符合条件的时间段里,说白了就是小于等于d的时间段里,去统计每个id的数量,如果一个id的数量大于k,就是热帖。由于时间段是不断向后枚举的,所以当时间段大于了d,就必须抛弃原时间段开头的那个元素,因此有这句代码:cnt[logs[j].y] –; ~~~ 半个月没刷题了 今天开始复习蓝桥杯 冲冲省二
大佬 我似乎终于懂了
#### 贴一个单调队列的。
你这个过不了啊
我的电脑可以过的
你说的好好笑
上面那个hh++不应该单独列出来,应该从hh开始。现在这个是对的
感谢大佬,注释也很可爱
为什么foe循环里面是while循环而不是if判断呀
每个i都需要通过起始的j不断移动来判断
为啥过不了啊
注释里应该是在
i
时刻这题能否用滑动窗口来实现呢?
这不就是滑动窗口吗
懂啦!谢谢大佬 好生动的注解
#include[HTML_REMOVED]
using namespace std;
int main() {
int N, D, K;
cin >> N >> D >> K;
}
看起来就是滑动窗口
哈希表存储遍历时间
看上去两层循环,时间复杂度应该是o(n),就是把所有事件都遍历了两遍
大佬帮忙看看,为什么用加法过不了这题啊
#include[HTML_REMOVED]
#include[HTML_REMOVED]
#include[HTML_REMOVED]
using namespace std;
const int N=1e5+10;
int n,d,k;
int cnt[N];
bool st[N];
#define ts first
#define id second
pair[HTML_REMOVED]g[N];
int main()
{
scanf(“%d%d%d”,&n,&d,&k);
for(int i=1;i<=n;i)
{
scanf(“%d%d”,&g[i].ts,&g[i].id);
}
sort(g+1,g+n+1);//直接对时间进行排序,然后只统计在这段时间内每种id的点赞数就行了
printf(“排序后\n”);
for(int i=1;i<=n;i)
{
printf(“%d %d\n”,g[i].ts,g[i].id);
}
for(int i=1,j=1;i<=n;i)
{
memset(cnt,0,sizeof cnt);
printf(“gg\n”);
while(g[j].ts-g[i].ts[HTML_REMOVED]= k) st[g[j].id] = true;
j;
}
if (cnt[g[j].id] >= k) st[g[j].id] = true;
}
}
你把你代码放到两组三个点之间,就能格式化显示
谁可以优化一下我的代码,我是枚举的id,最后一组数据超时了
懂了 tql
这里为啥i是走前面,j是走后面?,i不是后指针吗,j才是前指针吧,如果while循环里面条件满足,不是j就往后走一步吗
在这里,题意说是左闭右开
[i,i+k)
,包含为k,但是在这里转化为了左闭右闭[j,i]
,i-j<=k-1,同样包含k个时间点nb!!!
logs[i].x 和logs[j].x的id怎么保证想等的啊?
评价