⭐例题 Genius_ACM
考虑到二分会有很多低效的操作(如:二分第一步检验 这么长一段但右端点只会移动很少的部分),直接换倍增写。
- 初始化
- 求出
区间的“检验值” ,若 检验值
则
,否则
- 重复上一步直到
,此时 R 为所求值
#include <bits/stdc++.h>using namespace std;using ll = long long;const int N = 500006;int n, m, w;ll k, a[N], b[N], c[N];void gb(int l, int mid, int r) {int i = l, j = mid + 1;for (int k = l; k <= r; k++)if (j > r || (i <= mid && b[i] <= b[j])) c[k] = b[i++];elsec[k] = b[j++];}ll f(int l, int r) {if (r > n) r = n;int t = min(m, (r - l + 1) >> 1);for (int i = w + 1; i <= r; i++) b[i] = a[i];sort(b + w + 1, b + r + 1);gb(l, w, r);ll ans = 0;for (int i = 0; i < t; i++)ans += (c[r - i] - c[l + i]) * (c[r - i] - c[l + i]);return ans;}void Genius_ACM() {cin >> n >> m;cin >> k;for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);int ans = 0, l = 1, r = 1;w = 1;b[1] = a[1];while (l <= n) {int p = 1;while (p) {ll num = f(l, r + p);if (num <= k) {w = r = min(r + p, n);for (int i = l; i <= r; i++) b[i] = c[i];if (r == n) break;p <<= 1;} elsep >>= 1;}ans++;l = r + 1;}cout << ans << endl;}int main() {int t;cin >> t;while (t--) Genius_ACM();return 0;}
