感受
似乎贪心就解决这个问题了,为什么当时比赛过得人这么少?
思路
首先,我们处在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; }