从题目上看还是常规的模拟大题,我感觉考察的算法不是很多,关键还是对数据结构的理解,以及如何更好的利用
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++;
}
}
}