日志统计(2018年第九届蓝桥杯JavaB组省赛 第七题)
【题目描述】
小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。
其中每一行的格式是:ts id。表示在ts时刻编号id的帖子收到一个"赞"。
现在小明想统计有哪些帖子曾经是"热帖"。
如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。
具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。
给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。
【输入格式】
第一行包含三个整数N、D和K。
以下N行每行一条日志,包含两个整数ts和id。
1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000
【输出格式】
按从小到大的顺序输出热帖id。每个id一行。
【样例输入】
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
【样例输出】
1
3
测试网址:http://oj.ecustacm.cn/problem.php?id=1373
个人解法
【解法一】
代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
public class _日志统计 {
static int N, D, K;
static Map<Integer, ArrayList<Integer>> map = new HashMap<Integer, ArrayList<Integer>>();
public static void main(String[] args) throws IOException {
InputReader sc = new InputReader(System.in);
N = sc.nextInt();
D = sc.nextInt();
K = sc.nextInt();
for (int i = 0; i < N; ++i) {
int ts = sc.nextInt(), id = sc.nextInt();
if (!map.containsKey(id))
map.put(id, new ArrayList<Integer>());
map.get(id).add(ts);
}
Set<Integer> keys = map.keySet();
PriorityQueue<Integer> ans = new PriorityQueue<Integer>();
for (int key : keys) {
if (calculation(map.get(key)))
ans.add(key);
}
while(!ans.isEmpty())
System.out.println(ans.poll());
}
/**
* 双指针
*
* @param list
* @return
*/
public static boolean calculation(ArrayList<Integer> list) {
Collections.sort(list);
Integer[] ints = list.toArray(new Integer[list.size()]);
int leInd = 0, riInd = 0, curTotal = 0;
while (riInd < ints.length) {
if (ints[riInd] - ints[leInd] < D) {
++curTotal;
++riInd;
if (curTotal == K)
return true;
} else {
++leInd;
--curTotal;
}
}
return false;
}
static class InputReader {
StreamTokenizer tokenizer;
public InputReader(InputStream stream) {
tokenizer = new StreamTokenizer(new BufferedReader(new InputStreamReader(stream)));
tokenizer.ordinaryChars(33, 126);
tokenizer.wordChars(33, 126);
}
public String next() throws IOException {
tokenizer.nextToken();
return tokenizer.sval;
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
}
}
【简写版】
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class _日志统计 {
static ArrayList<Integer>[] list = new ArrayList[100000 + 5];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(), D = sc.nextInt(), K = sc.nextInt();
for (int i = 0; i < list.length; ++i)
list[i] = new ArrayList<Integer>();
for (int i = 0; i < N; ++i) {
int ts = sc.nextInt(), id = sc.nextInt();
list[id].add(ts);
}
for (int i = 0; i < list.length; ++i) {
if (list[i].size() != 0) {
Collections.sort(list[i]);
if(calculation(list[i].toArray(new Integer[list[i].size()]), D, K))
System.out.println(i);
}
}
}
public static boolean calculation(Integer[] ints, int D, int K) {
int leInd = 0, riInd = 0, curTotal = 0;
while (riInd < ints.length) {
if (ints[riInd] - ints[leInd] < D) {
++curTotal;
++riInd;
if (curTotal == K)
return true;
} else {
++leInd;
--curTotal;
}
}
return false;
}
}
【其他博主的解法 (具体是哪位博主的我已经不记得了,只是测试过他的代码,在测试网站上有保留)】
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1e5 + 10;
vector<int>v[maxn];
int n, d, k;
int b[maxn];
int ans[maxn];
int tot, cnt;
int main() {
cin >> n >> d >> k;
int x, y;
for(int i = 1; i <= n; i++) {
cin >> x >> y;
v[y].push_back(x);
}
for(int i = 0; i < maxn; i++) {
if(v[i].size() != 0)
sort(v[i].begin(), v[i].end());
for(int j = 0; j < v[i].size(); j++) {
int ed = j + k - 1;
if(ed >= v[i].size()) break;
if(v[i][ed] - v[i][j] < d) {
ans[cnt++] = i;
break;
}
}
}
for(int i = 0; i < cnt; i++) cout << ans[i] << endl;
return 0;
}
【其他博主的解法 (具体是哪位博主的我已经不记得了,只是测试过他的代码,在测试网站上有保留)】
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int[] num=new int[100005];
int[] ans=new int[100005];
int n=scan.nextInt();
int d=scan.nextInt();
int k=scan.nextInt();
Node[] a=new Node[100005];
for(int i=0;i<n;i++) {
Node node=new Node();
a[i]=node;
a[i].t=scan.nextInt();
a[i].id=scan.nextInt();
}
Arrays.sort(a,0,n,new Comparator<Node>() {
public int compare(Node p1,Node p2) {
return p1.t == p2.t ? p1.id-p2.id : p1.t-p2.t;
}
});
int i=0,j=0;
int l=a[i].t,r=a[j].t;
int x;
while(j<n) {
while(j<n && a[i].t+d>a[j].t) {
num[a[j].id]++;
if(num[a[j].id]>=k) {
ans[a[j].id] = 1;
}
j++;
}
num[a[i].id]--;
i++;
}
for(i=0;i<=100000;i++)
if(ans[i]!=0)
System.out.println(i);
}
}
class Node{
int t;
int id;
}