Question 问题 CF1858B The Walkway
题目大意: 有 n n n 个板凳,小 P 想要从第 1 1 1 个板凳走到第 n n n 个。小 P 在第 i i i 个板凳会吃饼干当且满足至少一个下列的要求:
- 第 i i i 个长凳附近有一个饼干卖家。
- 当前处于第 1 1 1 个长凳。
- 前 d d d 分钟没有吃饼干。
若同时满足多个要求,只吃一个饼干。可以移除一个饼干商家。问小 P 最少可以吃多少个饼干以及有多少种合法移除。
Analysis 分析
考虑移除一个商家会带来的影响。可发现小 P 从第 1 1 1 个板凳走到第 i − 1 i-1 i−1 个饼干店和第 i + 1 i+1 i+1 个饼干店到最后第 n n n 个板凳所要吃的饼干是不变的。也就是说,唯一会改变的是第 i − 1 i-1 i−1 个饼干店到第 i + 1 i+1 i+1 个饼干店这一段要吃的饼干。
总饼干数量可抽象为以下三段的贡献:
( 1 → s i − 1 ) + ( s i − 1 → s i + 1 ) + ( s i + 1 → n ) \left(1 \to s_{i-1} \right) + \left(s_{i-1} \to s_{i+1} \right) + \left(s_{i+1} \to n \right) (1→si−1)+(si−1→si+1)+(si+1→n)
Solution
这边为了方便,我们在第 n n n 个板凳处建一个"饼干店",但不参与吃饼干的计算。即 s m + 1 = n s_{m+1}=n sm+1=n。
我们记:
p r e i pre_i prei 代表从第 1 1 1 个板凳走到第 i i i 个饼干店要吃的饼干。即上面的 ( 1 → s i ) \left(1 \to s_{i} \right) (1→si)。
l s t i lst_i lsti 代表从第 i i i 个板凳走到第 n n n 个板凳要吃的饼干。 ( s i → n ) \left(s_{i} \to n \right) (si→n)。
那么移除第 i i i 个饼干店后要吃的饼干就等于:
p r e i − 1 + ⌊ s i + 1 − s i − 1 − [ i ≠ m ] d ⌋ + l s t i + 1 pre_{i-1}+ \lfloor \frac{s_{i+1}-s_{i-1}-[i \neq m]}{d} \rfloor +lst_{i+1} prei−1+⌊dsi+1−si−1−[i=m]⌋+lsti+1
具体细节见代码。
Code 代码
int t,n,m,d;
int s[N];
ll lst[N],pre[N],ans=INF;
int main(){
read(t);
while(t--){
read(n,m,d);ans=INF;
for(rint i=1;i<=m;i++) read(s[i]);
pre[0]=1;s[0]=1;s[m+1]=n;lst[m+1]=0;//预处理
for(rint i=1;i<=m;i++){
if(s[i]==1) pre[i]=1;
else pre[i]=pre[i-1]+(s[i]-s[i-1]-1)/d+1;
}//pre的预处理
for(rint i=m;i>=1;i--) lst[i]=(s[i+1]-s[i]-(i!=m))/d+lst[i+1]+1;//lst的预处理
ll res=0,cnt=0;
for(rint i=1;i<=m;i++){
res=pre[i-1]+(s[i+1]-s[i-1]-(i!=m))/d+lst[i+1];
if(res<ans) ans=res,cnt=1;
else if(res==ans) cnt++;//注意题目统计的是移除哪些饼干店可以打到吃最少饼干的要求
}
printf("%lld %lld\n",ans,cnt);
}
return 0;
}