[JOI 2024 Final] 室温
[JOI 2024 Final] 室温
题意
给出一个长度为 \(n\) 的序列 \(a\),给出数 \(T\)。
可以进行若干次操作,每次操作可以任选数 \(a_i\),将 \(a_i \leftarrow a_i - T\)。
可以选定一个数 \(t\),使得操作完成后 \(\max |a_i-t|\) 最小 。
思路
首先进行操作等价于将 \(a_i \leftarrow a_i \bmod T\)。
然后考虑对于固定的序列 \(a\),如何选定 \(t\) 使答案最小。
当 \(t = \frac{\min a_i + \max a_i}{2}\) 时,总答案最小。
因为当选定的 \(t = \min a_i\) 或 \(\max a_i\) 时,答案为 \(\max a_i - \min a_i\)。
当 \(t\) 往中间走的时候,答案会变小,最小时就是 \(t\) 取到中点时,答案为极差的一半。
如果除不尽怎么办呢?是向上取整还是向下取整?
应该是向上取整,因为除不尽时 \(t\) 一定往左或往右偏一点,较长的为答案,就是向上取整。
现在问题就变为了求出序列最小的极差,除以二向下取整就是答案。
首先想到将 \(a_i \bmod T\) 后排序,\(a_n-a_1\) 就是最小极差,但发现样例都不过。
发现问题:我可以将 \(a_1\) 到 \(a_i\) 的数少减一个 \(T\),变为 \(a_1+T\) 到 \(a_i+T\)。
这样新的极差就变为了 \(a_i+T-a_{i+1}\),枚举每个 \(i\) 取最小值即可。
注意原始的极差也要统计入答案。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 5;
int ans = 1e18, n, t, a[N];
signed main() {
cin >> n >> t;
for (int i = 1; i <= n; i ++)
cin >> a[i], a[i] %= t;
sort(a + 1, a + n + 1);
ans = (a[n] - a[1] + 1) / 2;
for (int i = 1; i < n; i ++)
ans = min(ans, (a[i] + t - a[i + 1] + 1) / 2);
cout << ans;
return 0;
}
本文来自博客园,作者:maniubi,转载请注明原文链接:https://www.cnblogs.com/maniubi/p/18449280,orz