打卡信奥刷题(3429)用C++实现信奥题 P10224 [COCI 2023/2024 #3] Vrsar

P10224 [COCI 2023/2024 #3] Vrsar

题目背景

译自 COCI 2023/2024 Contest #3 T2「Vrsar

题目描述

Vrsar 是一个由 n n n 座小山丘组成的海滨小镇。惊人地,从海岸看去, n n n 座山丘排成一列,第 i i i 座山丘到海岸的距离为 x i x_i xi 米。在每座山丘顶上各有一个溜冰场。所有溜冰场每天同时开放,但它们的关闭时间是不同的。第 i i i 座溜冰场开放 t i t_i ti 分钟。

Iva 和 Mia 已经来到了 Vrsar,他们将在这里停留 m m m 天。Iva 和 Mia 热爱溜冰,他们希望在 Vrsar 停留的每一天都以溜冰度过。在第 i i i 天的开始,他们距离海岸 a i a_i ai 米。当滑雪场开放的同时,他们开始他们的溜冰之旅。他们需要走去滑雪场,走路的速度为每分钟 1 1 1 米。

他们的身体非常好,因此他们不需要额外时间来爬山。一旦他们到达山顶的滑雪场,他们可以滑任意长的时间,直到滑雪场关闭。然而,下山并不像上山一样容易,因为下雨,山路非常湿滑,他们需要消耗 s i s_i si 的时间走下第 i i i 座山。从一座山上下来后,他们可以前往另一座山。

Iva 和 Mia 想知道每天他们最长可以滑多久的雪。每天他们可以访问任意多座滑雪场。因为他们想用尽可能多的时间滑雪,用尽可能少的时间计算,所以他们向你寻求帮助。帮助他们解决这个问题。

请注意:如果 Iva 和 Mia 早晨出发的位置就有一座山,他们在山脚。

输入格式

第一行包含两个整数 n , m n,m n,m 1 ≤ n , m ≤ 10 5 1 \le n,m \le 10^5 1n,m105),表示山的数量和天数。

接下来 n n n 行,第 i i i 行包含三个整数 x i , t i , s i x_i,t_i,s_i xi,ti,si 0 ≤ x i , t i , s i ≤ 10 9 0 \le x_i,t_i,s_i \le 10^9 0xi,ti,si109),分别表示第 i i i 座山到海岸的距离、滑雪场的关闭时间和下山所需的时间。

第三行包含 m m m 个整数 a i a_i ai 1 ≤ a i ≤ 10 9 1 \le a_i \le 10^9 1ai109),表示 Iva 和 Mia 第 i i i 天出发时到海岸的距离。

输出格式

输出一行 m m m 个整数,第 i i i 个整数表示第 i i i 天 Iva 和 Mia 可以滑雪的最长时间。

输入输出样例 #1

输入 #1

3 1
3 7 0
6 11 3
10 13 5
1

输出 #1

6

输入输出样例 #2

输入 #2

3 2
5 10 3
3 6 1
1 5 0
0 3

输出 #2

5 8

输入输出样例 #3

输入 #3

1 3
3 3 3
0 1 2

输出 #3

0 1 2

说明/提示

样例解释 1

Iva 和 Mia 在位置 1 1 1 出发,走 2 2 2 分钟到位置 3 3 3 的山,并滑雪 5 5 5 分钟。接着花费 0 0 0 分钟时间下山,继续走 3 3 3 分钟时间到位置 6 6 6 山上的滑雪场,滑雪 1 1 1 分钟。

他们一共滑雪 6 6 6 分钟。

子任务

SubtaskPointsConstraints
18 n , m ≤ 10 n,m \le 10 n,m10
217 m = 1 , a 1 = 0 m=1,a_1=0 m=1,a1=0
319 n , m ≤ 1000 n,m \le 1000 n,m1000
426无特殊限制。

C++实现

#include<bits/stdc++.h>
using namespace std;
const int _=1e5+5;
int n,m,dis[_],l[_],r[_],p,t;
struct node
{	int x,t;
	bool operator <(const node &o)const{	return x<o.x;}; 
}	a[_];
inline int read()
{	int x=0;char ch=getchar();
	for(;ch<'0'||'9'<ch;ch=getchar());
	for(;'0'<=ch&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
	return x;
}
inline void print(int x)
{	if(x>9)	print(x/10);
	putchar(x%10+'0');
}
signed main(){	
	n=read(),m=read();
	for(int i=1;i<=n;i++)	a[i].x=read(),a[i].t=read(),read();
	sort(a+1,a+n+1),l[0]=r[n+1]=-(1<<30);
	for(int i=1;i<=n;i++)	dis[i]=a[i].x,l[i]=max(l[i-1],a[i].x+a[i].t);
	for(int i=n;i>0;i--)	r[i]=max(r[i+1],a[i].t-a[i].x);
	for(int i=1;i<=m;i++)
	{	p=read();
		if(p<=dis[1])	print(r[1]+p);
		else if(dis[n]<=p)	print(l[n]-p);
		else	
		{	t=upper_bound(dis+1,dis+n+1,p)-dis;
			print(max(r[t]+p,l[t-1]-p));
		}
		if(i!=m)	putchar(' ');
	}
	return 0;
}

在这里插入图片描述

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值