诶算是一次想出来解法了
考虑枚举连续的k个元素,最后统一高度为x,ans = sigma( abs( xi - x ) )
用一点数学知识就能知道,当x为xi的中位数的时候答案最优
Treap维护枚举的连续k个元素(需要记录每个子树的和),求中位数(第k/2大)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#define N 400050
#define INF 1000000000
using namespace std;
typedef long long LL;
LL sum[N],tr[N],tot,pre,ter,v,ans;
int ls[N],rs[N],siz[N],r[N],a[N],rt,cnt,n,k;
inline void ut(LL &x,LL y) { x = min(x,y); }
inline void update(int &t) {
if (!t) return ;
sum[t] = sum[ ls[t] ] + sum[ rs[t] ] + tr[t];
siz[t] = siz[ ls[t] ] + siz[ rs[t] ] + 1;
}
inline void lturn(int &t) {
int d = rs[t];
rs[t] = ls[d];
ls[d] = t;
update(t); update(d);
t = d;
}
inline void rturn(int &t) {
int d = ls[t];
ls[t] = rs[d];
rs[d] = t;
update(t); update(d);
t = d;
}
void ins(int x,int &t) {
if (!t) {
tr[ t=++cnt ] = 1LL * x;
sum[t] = 1LL * x;
siz[t] = 1LL;
r[t] = rand();
return ;
}
sum[t] += x; siz[t]++;
if (x <= tr[t]) {
ins(x,ls[t]);
if (r[ ls[t] ] > r[t]) rturn(t);
} else {
ins(x,rs[t]);
if (r[ rs[t] ] > r[t]) lturn(t);
}
}
void query(int k,int t) {
if (!t) return ;
if (k == siz[ ls[t] ] + 1) {
pre += sum[ ls[t] ] + tr[t];
v = tr[t];
return ;
}
if (siz[ ls[t] ] >= k)
query(k,ls[t]);
else
pre += sum[ ls[t] ] + tr[t] , query(k-siz[ls[t]]-1,rs[t]);
}
void dec(int x,int &t) {
if (!t) return ;
if (x == tr[t]) {
if (!(ls[t]*rs[t])) {
int tt = t;
t = ls[t] + rs[t];
//update(t);
tr[tt] = siz[tt] = sum[tt] = ls[tt] = rs[tt] = 0;
return ;
}
if (r[ ls[t] ] > r[ rs[t] ])
rturn(t) , siz[t]-- , sum[t] -= x , dec(x,rs[t]);
else
lturn(t) , siz[t]-- , sum[t] -= x , dec(x,ls[t]);
return ;
}
siz[t]--; sum[t] -= x;
if (x < tr[t]) dec(x,ls[t]); else dec(x,rs[t]);
}
void solve() {
ans = (1LL << 62);
for (int i=1;i<=k;i++) ins(a[i],rt) , tot += 1LL * a[i];
for (int i=k+1;i<=n;i++) {
pre = 0; query((k+1)/2 , rt);
ter = tot - pre;
LL p1 = (k+1)/2 , p2 = k - p1;
ut(ans, p1*v - pre + ter - p2*v);
ins(a[i],rt);
dec(a[i-k],rt);
tot = tot - a[i-k] + a[i];
}
pre = 0; query((k+1)/2 , rt);
ter = tot - pre;
LL p1 = (k+1)/2 , p2 = k - p1;
ut(ans, 1LL * p1 * v - pre + ter - p2 * v);
}
inline void init() {
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
init();
solve();
#ifdef ONLINE_JUDGE
printf("%lld\n",ans);
#else
printf("%I64d\n",ans);
#endif
return 0;
}