思路:
大模拟最重要的是理清思路,针对该题的几块内容来说。
对于地区:用map来存,用pair表示某个地区是风险区的连续的开始和结束时间。维护起来 也很简单。若日期为d的一天收到p地成为风险区的消息,就检查d是否在p是风险区的日期内,即p地在日期d是否为风险区,如果是,就把p地风险区的结束时间延长至d+6(取不到d+7)(如果p地是风险的连续日期为[a,b],那么d是b+1也是可以连起来的,40分可能是这里没处理好)。如果不是,就把p地的风险区的区间设为[d,d+6]。
对于漫游消息:用结构体表示,用vector数组存,二维数组也可以。第d天收到的消息就存到下标为d的数组里面。
处理结果:读入数据后。在存漫游消息的数组里遍历前六天到现在的所有漫游消息,对于遍历到的每条漫游消息都检查一下看是否满足条件,若满足就把这条消息里的人加入答案中。最后把答案排序去重输出就可以了。
代码(注释):
#include<bits/stdc++.h>
using namespace std;
int n,m,r;
struct Data{//漫游消息
int d,u,p;
};
vector<Data> v[1010];//存漫游消息
map<int,pair<int,int> > pos; //每个地区的风险区持续时间
map<int,bool> st;//每个地区是否曾被设为风险区
void setf(int p,int d){//将p地设为风险区,日期是d
if(!st[p]) pos[p]={d,d+6};
else{
if(d<=pos[p].second+1) pos[p].second=d+6;//可以连起来
else pos[p]={d,d+6};
}
st[p]=true;
}
bool check(int d1,int u,int p,int d){//检查<d1,u,p>这条漫游消息是否满足条件,d为当前日期
if(st[p]&&d1>=d-6&&d1<=d&&d1>=pos[p].first&&d<=pos[p].second) return true;
return false;
}
int main(){
cin>>n;
for(int h=0;h<n;h++){//h表示当前日期
cin>>r>>m;
for(int i=1;i<=r;i++){//读入风险区并更新
int t;
cin>>t;
setf(t,h);
}
for(int i=1;i<=m;i++){//读入漫游消息并存入
int d,u,p;
cin>>d>>u>>p;
if(d<=h) v[h].push_back({d,u,p});
}
vector<int> ans;//当天的风险名单
for(int i=(h-6>=0?h-6:0);i<=h;i++){//遍历漫游消息,满足的加入ans
for(int j=0;j<v[i].size();j++){
if(check(v[i][j].d,v[i][j].u,v[i][j].p,h)) ans.push_back(v[i][j].u);
}
}
sort(ans.begin(),ans.end());
ans.erase(unique(ans.begin(),ans.end()),ans.end());
cout<<h;
for(int i=0;i<ans.size();i++) cout<<" "<<ans[i];
cout<<endl;
}
system("pause");
}