历届真题 日志统计【第九届】【省赛】【B组】

资源限制

时间限制:1.0s   内存限制:256.0MB

  小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:

  ts id

  表示在ts时刻编号id的帖子收到一个"赞"。

  现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。

  具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。

  给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。

输入格式

  第一行包含三个整数N、D和K。
  以下N行每行一条日志,包含两个整数ts和id。

  对于50%的数据,1 <= K <= N <= 1000
  对于100%的数据,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


资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

注意:
main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include <xxx>
不能通过工程设置而省略常用头文件。

提交程序时,注意选择所期望的语言类型和编译器类型。

此题使用尺取法求解



import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static int N, D, K;

    public static void main(String[] arge) {
        Scanner scanner = new Scanner(System.in);
        N = scanner.nextInt();
        D = scanner.nextInt();
        K = scanner.nextInt();
        Data[] data = new Data[N + 1];
        for (int i = 0; i < N; i++) {
            data[i] = new Data();
            int x = scanner.nextInt();
            int y = scanner.nextInt();
            data[i].t = x;
            data[i].id = y;
        }
        data[N] = new Data(1000000+1, 1000000+1);// 防止月越界
        Arrays.sort(data);
//        for (int i = 0; i < data.length; i++) {
//            System.out.println(i+":"+data[i].t+","+data[i].id);
//        }

        int q = 0, h = 0, res = -1;

        int temp = 1;
        while ( data[h].id != 1000000+1) {

            q= Math.max(q, h);
            h=q;
            temp=1;

            while (data[q].id == data[h].id) {

                // 后指针后移动
                while (data[h].t == data[h + 1].t) {
                    h++;
                    temp++;
                }
                // 时间合理
                if (data[h].t - data[q].t <= D - 1) {
                    if (temp >= K) {// 数量正确,到下一张帖子
                        System.out.println(data[h].id);

                        while (data[q].id == data[h].id) {
                            h++;
                            temp = 0;

                            if(data[h].id==10){
                                int kkk=1;
                            }
                        }

                    } else {
                        // 如果后指针的下一节仍在这一段,则能移动
                        if(data[h+1].id==data[q].id) {
                            h++;
                            temp++;
                        }
                        else if(data[q].t==data[q].t){// 如果不在这一节
                            h++;
                        }
                    }
                } else {// 时间不合理
                    // 前指针前进
                    while (data[q].t == data[q + 1].t) {
                        q++;
                        temp--;
                    }
                    q++;
                }
            }


        }

    }



static class Data implements Comparable<Data> {
    public Data(int t, int id) {
        super();
        this.t = t;
        this.id = id;
    }

    public Data() {
        super();
    }


    int t;
    int id;

    public int compareTo(Data arg0) {
        // TODO Auto-generated method stub

        if (id == arg0.id) {
            if (t < arg0.t) {
                return -1;
            } else if (t == arg0.t) {
                return 0;
            } else {
                return 1;
            }
        } else {
            if (id < arg0.id) {
                return -1;
            } else {
                return 1;
            }
        }
    }
}}

优化后

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static int N, D, K;

    public static void main(String[] arge) {
        Scanner scanner = new Scanner(System.in);
        N = scanner.nextInt();
        D = scanner.nextInt();
        K = scanner.nextInt();
        Data[] data = new Data[N + 1];
        for (int i = 0; i < N; i++) {
            data[i] = new Data();
            data[i].t = scanner.nextInt();
            data[i].id = scanner.nextInt();
        }
        data[N] = new Data(1000000+1, 1000000+1);// 防止月越界

        Arrays.sort(data);
        int q = 0, h = 0, res = -1;
        int temp = 1;
        while ( data[h].id != 1000000+1) {
            q= Math.max(q, h);
            h=q;
            temp=0;
            while (data[q].id == data[h].id) {
                temp++;

                if(temp>=K){
                    if(data[h].t-data[q].t<D){
                        System.out.println(data[h].id);
                        while (data[h].id==data[q].id){
                            h++;
                        }
                        h--;
                    }else {
                        temp--;
                        q++;
                    }
                }
                h++;
            }

        }
    }

static class Data implements Comparable<Data> {
    public Data(int t, int id) {
        super();
        this.t = t;
        this.id = id;
    }
    public Data() {
        super();
    }
    int t;
    int id;
    public int compareTo(Data arg0) {
        // TODO Auto-generated method stub

        if (id == arg0.id) {
            return t-arg0.t;
        } else {
            return id-arg0.id;
        }
    }
}}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值