HNU程序设计训练2023—— 病毒传播

【问题描述】

       在一个风景秀丽的小镇,一天早上,有 N 名晨跑爱好者(编号 1 ~ N )沿着优雅的江边景观道朝同一方向进行晨跑,第 i 名跑者从位置 Si 处起跑, 且其速度为 Vi。换句话说,对所有的实数 t ≥ 0,在时刻 t 时第 i 名跑者的位置为 Si + Vi ·t。 

       很不幸的是,其中一名跑者在 t = 0 的时刻感染了病毒,且是无症状感染者,这种病毒只会在同一时刻处在同一位置的跑者之间传播,新感染了病毒的跑者也会感染其他人,很显然,等待足够长的时间,那么病毒会感染 一些特定的跑者。

       事后发现其中有一名跑者感染了病毒,如果此人就是在 t = 0 时刻的那名感染者,那么,在 N 名晨跑爱好者中会有多少人感染病毒?

【输入形式】

        输入包含三行:

    •  第一行包含为两个整数 N 和 K,分别表示运动员的人数以及开始时感染了病毒的跑者编号。

    •  第二行包含 个正整数 S1、S2、...、SN,用空格隔开,分别表示跑者的起始位置。

    •  第三行包含 个正整数 V1、V2、...、VN,用空格隔开,分别表示跑者的速度。

【输出形式】

         输出为一个整数,表示最终被感染人数。

【样例输入】

6 3
3 9 8 5 7 5
6 6 5 4 6 3

【样例输出】

3

【样例说明】
【评分标准】

     对于50%的评测用例,0< K ≤ ≤102

     对于70%的评测用例,0< ≤ ≤104

     对于90%的评测用例,0< ≤ ≤106

     对于100%的评测用例,0< ≤ ≤107

逆向思考:找到不被感染的人,与总人数相减后得到被感染人数

大量输入数据时,可考虑使用scanf代替cin流输入提速

#define _CRT_SECURE_NO_WARNINGS 1//去掉这句在vs中使用scanf有时会报一些神奇的错误
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;

struct People
{
	int s = 0;
	int v = 0;
	int id = 0;//编号
};
bool cmp(People a, People b)
{
	return a.s < b.s;//按照空间位置s排序
}
int n = 0, k = 0;
vector<People> people(10000001);

int main()
{
	int maxlv = -1;
	int minrv = INT_MAX;
	//找初始感染者左边的最大速度,右边的最小速度
	scanf("%d %d", &n, &k);
	//cin >> n >> k;,使用cin可能超时,使用scanf在cg提交对比可提速将近0.85s
	for (int i = 0; i < n; i++)
	{
	scanf("%d", &people[i].s);
		//cin >> people[i].s;
		people[i].id = i + 1;//编号
	}
	for (int i = 0; i < n; i++)
	scanf("%d", &people[i].v);
	//cin >> people[i].v;
	stable_sort(people.begin(), people.begin()+n, cmp);
	int mid = 0;//以初始感染者为轴
	for (int i = 0; i < n; i++)
	{
		if (people[i].v > maxlv)
			maxlv = people[i].v;//找到左边的最大速度
		if (people[i].id == k)
		{
			mid = i;
			break;
		}
	}
	for (int i = mid; i < n; i++)
	{
		if (people[i].v < minrv)
			minrv = people[i].v;//找到右边的最小值
	}
	//在初始感染者左边且速度小于右边的最小速度,不会追上感染者,安全
	//在初始感染者右边且速度大于左边的最小速度,不会被感染者追上,安全
	int safe = 0;
	for (int i = 0; i < n; i++)
	{
		if (i < mid && people[i].v <= minrv&&people[i].s<people[mid].s)
			safe++;
		else if (i > mid && people[i].v >= maxlv && people[i].s > people[mid].s)
			safe++;
	}
	cout << n - safe;//感染者等于全部减去未感染者
	return 0;
 }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值