fuxey必须%。。。
树状数组的话,其实就是相当于滑动窗口,然后用树状数组维护当前中位数,总和用前缀和搞一下,就可以直接算了。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int inf=0x7fffffff;
const int N=1e5+5;
int n,k;
int a[N];
typedef long long ll;
ll d1[N*10],d2[N*10],ans;
int mx;
inline int lowbit(int x)
{
return x&(-x);
}
inline void add(int x,int y,ll *d)
{
while (x<=mx)
{
d[x]+=y;
x+=lowbit(x);
}
}
inline ll query(int x,ll *d)
{
ll ans=0;
while (x>0)
{
ans+=d[x];
x-=lowbit(x);
}
return ans;
}
inline int find(int k,ll *d)
{
int ans=0,cnt=0;
fd(i,20,0)
{
ans+=1<<i;
if (ans>mx||cnt+d[ans]>=k)ans-=1<<i;
else cnt+=d[ans];
}
return ans+1;
}
int main()
{
scanf("%d%d",&n,&k);
fo(i,1,n)
{
scanf("%d",&a[i]);
mx=max(mx,a[i]);
}
fo(i,1,n+1)a[i]++;
int cnt=k;
ans=1e15;
ll sum=0;
fo(i,1,k)
add(a[i],1,d1),
add(a[i],a[i],d2),sum+=a[i];
while(cnt<=n)
{
int now=find((k+1)/2,d1);
ll m1=query(now,d1);
ll m2=query(now,d2);
ans=min(ans,sum-2*m2+m1*now-(k-m1)*now);
sum-=a[cnt-k+1];
add(a[cnt-k+1],-1,d1);
add(a[cnt-k+1],-a[cnt-k+1],d2);
sum+=a[cnt+1];
add(a[cnt+1],1,d1);
add(a[cnt+1],a[cnt+1],d2);
cnt++;
}
printf("%lld\n",ans);
}