题目描述
小明维护着一个程序员论坛。现在他收集了一份”点赞”日志,日志共有 N行。
其中每一行的格式是:ts id
表示在 ts时刻编号 id的帖子收到一个”赞”。
现在小明想统计有哪些帖子曾经是”热帖”。
如果一个帖子曾在任意一个长度为 D的时间段内收到不少于 K个赞,小明就认为这个帖子曾是”热帖”。
具体来说,如果存在某个时刻 T
满足该帖在 [T,T+D) 这段时间内(注意是左闭右开区间)收到不少于 K个赞,该帖就曾是”热帖”。
给定日志,请你帮助小明统计出所有曾是”热帖”的帖子编号。
输入格式
第一行包含三个整数 N,D,K。
以下 N行每行一条日志,包含两个整数 ts 和 id。
输出格式
按从小到大的顺序输出热帖 id。
每个 id占一行。
数据范围
1≤K≤N≤105,
0≤ts,id≤105,
1≤D≤10000
输入样例:
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
输出样例:
1
3
相似题目
思路:
1.我们要判断一个帖子是不是热帖,就要知道它在某个
区间内是否点赞数大于等于K,而且这个区间还要有序才
能保证答答案的正确性,这就要把时间与对应的id,一
起排序,需要定义一个类,然后用ArrayList.sort去
排序;
class Ps implements Comparable<Ps>{
public int t;
public int id;
public Ps(int t,int id){
this.t=t;
this.id=id;
}
public int compareTo(Ps o){
return Integer.compare(t,o.t);
}
}
2.排好序后我们就在双指针加滑动窗口在规定的区间
里找,不能两重循环暴力找会超时,只能过百分之五
十的数据;
3.用j,i分别表示窗口的左右边界,每次遍历的时候
hot[ps[i].id]++;
当ps[i].t-ps[j].t>=D的时候窗口就要缩小,还要
把左边界所指的那个时间的对应的店铺热度减掉,即
hot[ps[j].id]--;
4.经过上述操作后如果当前时间点对应的店铺的热度
大于等于K,则表示这个店铺是热帖;
代码
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int N=input.nextInt();
int D=input.nextInt();
int K=input.nextInt();
Ps[] logs = new Ps[N+1];
int ans[]=new int[1000000];
int hot[]=new int[1000000];
for(int i=0;i<N;i++){
int t=input.nextInt();
int id=input.nextInt();
logs[i] = new Ps(t,id);
}
Arrays.sort(logs,0,N);
for(int i=0,j=0;i<N;i++){
hot[logs[i].id]++;
while(logs[i].t-logs[j].t>=D){
hot[logs[j].id]--;
j++;
}
if(hot[logs[i].id]>=K){
ans[logs[i].id]=1;
}
}
for(int i=0;i<1000000;i++){
if(ans[i]==1)
System.out.println(i);
}
}
}
class Ps implements Comparable<Ps>{
public int t;
public int id;
public Ps(int t,int id){
this.t=t;
this.id=id;
}
public int compareTo(Ps o){
return Integer.compare(t,o.t);
}
}