#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
const int N = 5e5 + 10;
const int INF = 0x3f3f3f3f;
ll qpow(ll base, ll n){ll ans = 1; while (n){if (n & 1) ans = ans * base % mod; base = base * base % mod; n >>= 1;} return ans;}
ll gcd(ll a, ll b){return b ? gcd(b, a % b) : a;}
ll a[N], b[N], c[N], t;
int n, m, old_r;
ll cal(int l, int r){
r = min(r, n);
int num = min(m, (r - l + 1) >> 1);
for (int i = l; i <= r; ++ i) b[i] = a[i];
sort(b + l, b + r + 1);
ll ans = 0;
for (int i = 0; i < num; ++ i) {
ans += (b[r - i] - b[l + i]) * (b[r - i] - b[l + i]);
}
return ans;
}
int main()
{
int k;
cin >> k;
while (k --){
cin >> n >> m >> t;
for (int i = 1; i <= n; ++ i){
scanf("%lld", &a[i]);
}
int l, r, p;
l = r = 1;
b[l] = a[l];
int ans = 0;
while (l <= n){
p = 1;
while (p){
ll num = cal(l, r + p);
if (num <= t){
r = min(r + p, n);
if (r == n) break;
p <<= 1;
}else p >>= 1;
}
++ ans;
l = r + 1;
r = l;
}
cout << ans << '\n';
}
return 0;
}
归并排序
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
const int N = 5e5 + 10;
const int INF = 0x3f3f3f3f;
ll qpow(ll base, ll n){ll ans = 1; while (n){if (n & 1) ans = ans * base % mod; base = base * base % mod; n >>= 1;} return ans;}
ll gcd(ll a, ll b){return b ? gcd(b, a % b) : a;}
ll a[N], b[N], c[N], t;
int n, m, old_r;
void merge(int l, int x, int r){
int i = l, j = x + 1;
for (int k = l; k <= r; ++ k){
if (j > r || (i <= x && b[i] <= b[j])) c[k] = b[i ++];
//新区间指针移到边界,或者旧区间指针还未移到边界并且所指元素小于新区间指针所指元素时
else c[k] = b[j ++];
}
}
ll cal(int l, int r){
r = min(r, n);
int num = min(m, (r - l + 1) >> 1);//元素不能重复利用
for (int i = old_r + 1; i <= r; ++ i) b[i] = a[i];//加进新元素
sort(b + old_r + 1, b + r + 1);//对新加进来的元素排序
merge(l, old_r, r);//将新元素与已排好的一段序列合并
ll ans = 0;
for (int i = 0; i < num; ++ i) {
ans += (c[r - i] - c[l + i]) * (c[r - i] - c[l + i]);//计算校验值
}
return ans;
}
int main()
{
int k;
cin >> k;
while (k --){
cin >> n >> m >> t;
for (int i = 1; i <= n; ++ i){
scanf("%lld", &a[i]);
}
int l, r, p;
l = r = old_r = 1;
b[l] = a[l];
int ans = 0;
while (l <= n){
p = 1;
while (p){
ll num = cal(l, r + p);
if (num <= t){//校验值小于t,说明范围可再扩大
old_r = r = min(r + p, n);
for (int i = l; i <= r; ++ i) b[i] = c[i];//b记录排好的序列,供下次merge使用
if (r == n) break;
p <<= 1;//p倍增
}else p >>= 1;//校验值大于t时,不断右移p,直到p为0,说明范围不可扩
}
++ ans;//段数++
l = r + 1;//下一点开始继续上述步骤
old_r = r = l;
}
cout << ans << '\n';
}
return 0;
}