CSP防疫大数据(Java)

3 篇文章 0 订阅

从题目上看还是常规的模拟大题,我感觉考察的算法不是很多,关键还是对数据结构的理解,以及如何更好的利用STL。另一方面,网上基本上都是c++,身为Java爱好者所以打算也写一下。(个人觉得写的有些冗余不过可以AC,凑合看吧)


import java.io.*;
import java.util.*;
class Node{
    int s;int e;//s:开始时间(包含) e:结束时间(不包含)
    Map<Integer,Integer> user;//用来存放该地区的人员,key:UID value:人员死亡时间(没更新只能活七天)
    Node(int s,int e){
        this.e=e;
        this.s=s;
        user=new TreeMap<>();//TreeMap根据key默认递增排序
    }
}

public class Main {

    public static void main(String[] args) throws IOException {
        read in=new read();

        PrintWriter pw=new PrintWriter(System.out);
        Map<Integer,Node> ps=new HashMap<>();//用来存风险区,key:ID value:风险区的信息
        int n=in.nextInt();
        int day=0;//统计当前是那天
        while (n-->0){
            int r=in.nextInt();
            int m=in.nextInt();
            //处理风险区
            while (r-->0){
                int p=in.nextInt();
                //true:包含且当前风险区还没过期
                if (ps.containsKey(p)&&ps.get(p).e>=day){
                    ps.get(p).e=day+7;//风险区没有延时所以直接生命周期加7
                }else {
                    ps.put(p,new Node(day,day+7));
                }
            }
            //处理人员活动信息
            while (m-->0){
                int d=in.nextInt();
                int u=in.nextInt();
                int ru=in.nextInt();

                if (day-d>=7&&d<0)continue;//7天前的和日期为负数的跳过
                if (ps.containsKey(ru)){//判断当前ru是不是风险区
                    if (d>=ps.get(ru).s&&d<ps.get(ru).e){//人去的时候是不是风险区间
                        if (ps.get(ru).user.containsKey(u)){//风险区之前有没有记录过此人
                            ps.get(ru).user.replace(u,Math.max( ps.get(ru).user.get(u),d+7));
                            //当前记录可能在原纪录之前或者之后,所以选活的最久的
                        }else {
                            ps.get(ru).user.put(u,d+7);//没记录过就直接扔进去
                        }
                    }


                }

            }
            Set<Integer> set=new TreeSet<>();//记录当天要输出信息,TreeSet去重加排序
            
            //此处用来更新风险区和过期人员,(提一句Map遍历过程中要进行删除操作时不能用for循环!)
            Iterator<Map.Entry<Integer,Node>> it=ps.entrySet().iterator();
            while(it.hasNext()){
                Map.Entry<Integer,Node> entry = it.next();
                Node p=entry.getValue();
                if(p.e<=day){//已经不是风险区
                    it.remove();
                }else if (!p.user.isEmpty()){//是风险区且名单上有人
                    Iterator<Map.Entry<Integer,Integer>> it2=p.user.entrySet().iterator();//遍历名单
                    while(it2.hasNext()){
                        Map.Entry<Integer,Integer> entry2 = it2.next();
                        int p2=entry2.getValue();
                        if (p2>day)//判断是不是最近7天的
                            set.add(entry2.getKey());
                        else
                            it2.remove();
                    }
                }
            }


            pw.printf("%d ",day);
            for (Integer i:set)
                pw.printf("%d ",i);
            pw.println();

            day++;
        }

        pw.flush();


    }
}
//多输入输出都要用,懂得都懂
class read{
    StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    int nextInt() throws IOException {
        st.nextToken();
        return (int)st.nval;
    }
    long nextLong() throws IOException {
        st.nextToken();
        return (long)st.nval;
    }

    String next() throws IOException {
        st.nextToken();
        return st.sval;
    }
}


总体思路就是创建一个风险区对象然后维护风险区的时间,风险区对象里面又包含一个人员列表,来统计来过此风险区的人,输出的时候就遍历全部风险区的人员列表。每天结束时处理一下过期的风险区或人。


另外提供一个数据生成器(参数可以自己改,建议n不要过大),往往知道自己为什么错比看别人的解法更加解压。微笑.jpg

public class tt {
    public static void main(String[] args) {

        Random random=new Random();
        int n=random.nextInt(30);
        int day=1;
        System.out.println(n);
        while (n-->0){
            int r=random.nextInt(10);
            int m=random.nextInt(10);
            System.out.printf("%d %d ",r,m);
            for (int i=0;i<r;i++){
                int p=random.nextInt(50);
                System.out.printf("%d ",p+1);
            }
            System.out.println();
            for (int i=0;i<m;i++){
                int d=random.nextInt(day);
                int u=random.nextInt(15);
                int ru=random.nextInt(50);
                System.out.printf("%d %d %d\n",d,u,ru);
            }
            day++;
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值