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 1≤n,m≤105),表示山的数量和天数。
接下来 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 0≤xi,ti,si≤109),分别表示第 i i i 座山到海岸的距离、滑雪场的关闭时间和下山所需的时间。
第三行包含 m m m 个整数 a i a_i ai( 1 ≤ a i ≤ 10 9 1 \le a_i \le 10^9 1≤ai≤109),表示 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 分钟。
子任务
| Subtask | Points | Constraints |
|---|---|---|
| 1 | 8 | n , m ≤ 10 n,m \le 10 n,m≤10 |
| 2 | 17 | m = 1 , a 1 = 0 m=1,a_1=0 m=1,a1=0 |
| 3 | 19 | n , m ≤ 1000 n,m \le 1000 n,m≤1000 |
| 4 | 26 | 无特殊限制。 |
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考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
4946

被折叠的 条评论
为什么被折叠?



