2020年百度之星·程序设计大赛-初赛二 -------Covid

题目大意:
Problem Description
科学家小沃沃在研究病毒传播的规律,从而控制疫情。

有 nn 个人,编号分别为 1,2,…,n1,2,…,n。我们用荧光粉代替病毒,编号为 1 的人,在第 0 时刻涂上了荧光粉,剩下的人在第 0 时刻没有涂。

对于第 ii 个人,我们知道这个人在哪些时刻出现在了哪些地方。

如果时刻 tt,某个人和身体上有荧光粉的人,出现在了同一地点,那么从时刻 tt 以后,这个人也会沾上荧光粉。

从小到大输出实验结束后身体上有荧光粉的人的编号。

Input
第一行一个整数 T(1 \leq T \leq 20)T(1≤T≤20) 表示 TT 组数据。

对于每组数据,第一行一个整数 n (1 \leq n \leq 20000)n(1≤n≤20000) 表示 nn 个人。

对于第 ii 个人,第一行输入一个整数 len[i](1 \leq len[i] \leq 100 )leni 表示这个人的活动轨迹。

接下来 len[i]len[i] 行,每行输入两个整数 t, p(1 \leq t \leq 100, 1 \leq p \leq 10)t,p(1≤t≤100,1≤p≤10) 表示这个人 tt 时刻出现在了 pp 位置,保证 tt 按严格递增的顺序给出。

除了这 len[i]len[i] 个时刻,这个人都呆在家里,或者换句话说,他/她不在任何位置。 保证 len[1] + len[2] + … + len[n] \leq 200000len[1]+len[2]+…+len[n]≤200000。

Output
对于每组数据输出一行,表示所有患者的编号。按编号从小到大输出。

Sample Input
2
4
2
1 1
2 2
3
2 2
3 3
4 4
1
4 4
1
2 1
3
3
1 1
3 1
6 1
3
4 1
5 1
6 1
1
5 1
Sample Output
Copy
1 2 3
1 2

样例解释
Case 1:
第 2 时刻,位置 2,1 与 2 相遇,2 沾上了。
第 4 时刻,位置 4,2 与 3 相遇,3 沾上了。
这个问题就是问你最后有多少人感染,并且按编号从小到大输出。解决这个问题主要是判断在同一时间同一地点出现过什么样得人。首先我们要开一个dis数组来表明这个人是否感染,然后再来找和他出现在同一时间同一地点的人。我们先将所有的时间地点记录下来,并且记录下它相应的编号,然后我们排序(先按时间,再按地点,最后按编号)。因为一个人的感染是按她感染后的时间,然后就进行找就可以了

代码:

#include <queue>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn =  2e5+9;

struct node
{
    ll id,t,p;
}a[maxn];
ll dis[maxn];
bool cmp(node x,node y)
{
    if(x.t!=y.t)
        return x.t<y.t;
    if(x.p!=y.p)
        return x.p<y.p;
    return x.id<y.id;
}
int main()
{
    ll t,n,m,i,j;
    scanf("%lld",&t);
    while(t--)
    {
        memset(dis,0,sizeof(dis));
        scanf("%lld",&n);
        ll ant=0;
        for(i=1;i<=n;i++)
        {
            scanf("%lld ",&m);
            for(j=0;j<m;j++)
            {
                scanf("%lld %lld",&a[ant].t,&a[ant].p);
                a[ant].id=i;
                ant++;
            }
        }
        sort(a,a+ant,cmp);
        dis[1]=1;
        for(i=1;i<ant;i++)
        {
            if(dis[a[i].id]==1||dis[a[i-1].id]==1)
            {
                if(a[i].t==a[i-1].t&&a[i].p==a[i-1].p)
                {
                     dis[a[i].id]=1;
                dis[a[i-1].id]=1;
                j=i;
                while(a[j].t==a[j-1].t&&a[j].p==a[j-1].p)
                {
                    dis[a[j-1].id]=1;
                    dis[a[j].id]=1;
                    j--;
                }
                }


            }
        }
        printf("1");
        for(i=2;i<=n;i++)
        {
            if(dis[i])
                printf(" %lld",i);
        }
        printf("\n");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值