在线维护中位数,大于等于中位数的放到一个set里,小于中位数的放到另一个set里。如果两个set大小不同就调整一下。
注意,n=1时需要特判。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int N = 1e5 + 5, M = 5e2 + 5, base = 131;
const int inf = 0x3f3f3f3f3f3f3f3f, MOD = 1e9 + 7;
int n, k, mid;
int a[N];
multiset<int>st1, st2;
multiset<int>::iterator it;
void solve()
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
if (n == 1)
{
cout << 0 << endl;
cout << a[1] << endl;
return;
}
int res1 = 0, res2 = 0;
mid = a[1], st2.insert(a[1]), res2 += a[1];
int ans = inf, ansmid = 0, idx = 0;
for (int i = 2; i <= n; i++)
{
if (i > k)
{
if (a[i - k] >= mid) st2.erase(st2.find(a[i - k])), res2 -= a[i - k];
else st1.erase(st1.find(a[i - k])), res1 -= a[i - k];
}
if (a[i] >= mid) st2.insert(a[i]), res2 += a[i];
else st1.insert(a[i]), res1 += a[i];
while (st1.size() + 1 < st2.size())
{
it = st2.begin();
res2 -= *it;
res1 += *it;
st1.insert(*it);
st2.erase(it);
}
while (st1.size() > st2.size())
{
it = prev(st1.end());
res1 -= *it;
res2 += *it;
st2.insert(*it);
st1.erase(it);
}
mid = *st2.begin();
if (i >= k)
{
int sum = 0;
sum += (res2 - mid * (int)(st2.size()));
sum += (mid * (int)(st1.size()) - res1);
if (ans >= sum)
{
ans = sum;
ansmid = mid;
idx = i;
}
}
}
cout << ans << endl;
for (int i = idx - k + 1; i <= idx; i++) a[i] = ansmid;
for (int i = 1; i <= n; i++)
{
cout << a[i] << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
// cin >> T;
for (int i = 1; i <= T; i++)
{
solve();
}
return 0;
}