感受
似乎贪心就解决这个问题了,为什么当时比赛过得人这么少?
思路
首先,我们处在p位置,显然要么向左走到相邻的城市,要么向右走走到相邻的城市。
有一个不会证明但观察到的结论,从这两个位置走的话,只有四种可能。
可能1:一直向左走
可能2:一直向右走
可能3:一直向左走到第i个城市,然后再向右走到第i+1个城市,然后再向左走到第i个城市,然后再向右走到第i+1个城市...
可能4:一直向右走到第i个城市,然后再向左走到第i-1个城市,然后再向右走到第i个城市,然后再向左走到第i-1个城市...
观察的结论讲实话我也不会证明,坐等明天题解
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
const ll inf = 1e18;
int n, m; ll p;
ll a[maxn];
ll solve1(int r, int m){
if(r > n || r < 1) return inf;
ll tmp = inf;
for(int i = r; i <= n; i++){
ll v = a[i] - a[r];///经过了i - r + 1座城市
if(i == 1){
if(m == 1) tmp = 0;
}
else{
tmp = min(tmp, v + (a[i] - a[i - 1]) * max((m - (i - r + 1)), 0));
}
}
return tmp;
}///r位置一直向右延伸
ll solve2(int l, int m){
if(l < 1 || l > n) return inf;
ll tmp = inf;
for(int i = l; i >= 1; i--){
ll v = a[l] - a[i];///经过了l - i + 1座城市
if(i == n){
if(m == 1) tmp = 0;
}
else{
tmp = min(tmp, v + (a[i + 1] - a[i]) * max((m - (l - i + 1)), 0));
}
}
return tmp;
}///l位置一直向左延伸
int main(){
int t;
scanf("%d", &t);
while(t--){
scanf("%d%d%lld", &n, &m, &p);
ll ans = inf;
int l, r;
for(int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
}
l = upper_bound(a + 1, a + n + 1, p) - a; r = l;
l--;
ans = min(ans, a[r] - p + solve1(r, m));
ans = min(ans, p - a[l] + solve1(l, m));
ans = min(ans, a[r] - p + solve2(r, m));
ans = min(ans, p - a[l] + solve2(l, m));
printf("%lld\n", ans);
}
return 0;
}



京公网安备 11010502036488号