import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
/*
本题采用滑动区间的做法,按时间排序,每次处理区间长度为d内的数
for循环里面嵌套while,for循环里的i不断自增
当i - j >= d 时 (注意这里要取等) 把左区间j自增,然后j对应的id删掉
*/
public class Main{
static int n,d,k;
static int N = 100010;
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static int[] cnt = new int[N]; //表示id为i的数
static PII[] p = new PII[N]; //存储输入的时间和id
static boolean[] st = new boolean[N]; //判断st[i]曾经是否是热帖
public static void main(String[] args) throws IOException {
String[] init = in.readLine().split(" ");
n = Integer.parseInt(init[0]);
d = Integer.parseInt(init[1]);
k = Integer.parseInt(init[2]);
for (int i = 0; i < n; i++) {
//init数组可以复用
init = in.readLine().split(" ");
int ts = Integer.parseInt(init[0]);
int id = Integer.parseInt(init[1]);
p[i] = new PII(ts,id);
}
Arrays.sort(p,0,n); //重写了Comparable接口,按时间排序
for (int i = 0,j = 0; i < n; i++) {
int id = p[i].id;
//每次处理的是id为i的数,不是第i个数
cnt[id]++;
//每次维护该窗口,i不断往前的同时,当i - j >= d 时
//要把j往前,同时把j对应的id删掉
while (p[i].ts - p[j].ts >= d){
//这个时候区间长度为 d + 1,要舍去最左边那个id
cnt[p[j].id]--;
j++;
}
//该窗口内,该id出现此处 >= k时,就代表它是热帖
if (cnt[id] >= k){
st[id] = true;
}
}
//打印所有热帖
//因为st[i]代表 id为 i 的数是否是热帖
//不是第i个数是否是热帖,所以循环条件是i < N
//对应,输出的时候直接输出i就行
for (int i = 0; i < N; i++) {
if (st[i] == true)
System.out.println(i);
}
in.close();
}
static class PII implements Comparable<PII>{
int ts;
int id;
public PII(int ts, int id) {
this.ts = ts;
this.id = id;
}
@Override
public int compareTo(PII o) {
//按时间排序,可以不用按id排序
///因为要统计的是每个区间每个id出现的次数,即使乱序也没事
return Integer.compare(this.ts,o.ts);
}
}
}
AcWing1238.日志统计(java版)
于 2023-11-29 20:37:03 首次发布