枚举每一个区间,用treap维护中位数和子树和更新答案
PS:treap代码风格一变再变,从指针(太难调试+太长了)->结构体(太长了)->数组
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e5+10;
typedef long long ll;
const ll linf=9223372036854775807LL;
int l[N],r[N],s[N],w[N],rnd[N],K;
ll v[N],sum[N],sum1,sum2,tmp,ans=linf,h[N];
int n,m,size,root;
void update(int k)
{
s[k]=s[l[k]]+s[r[k]]+w[k];
sum[k]=sum[l[k]]+sum[r[k]]+w[k]*v[k];
}
void rturn(int &k) {int t=l[k];l[k]=r[t];r[t]=k;update(k);update(t);k=t;}
void lturn(int &k) {int t=r[k];r[k]=l[t];l[t]=k;update(k);update(t);k=t;}
void insert(int &k,int val)
{
if(k==0) {k=++size;v[k]=sum[k]=val;rnd[k]=rand();s[k]=w[k]=1;return ;}
sum[k]+=val;s[k]++;
if(v[k]==val) w[k]++;
else if(val>v[k]){
insert(r[k],val);if(rnd[r[k]]<rnd[k])lturn(k);}
else {
insert(l[k],val);if(rnd[l[k]]<rnd[k])rturn(k);}
}
void del(int &k,int val)
{
if(k==0) return ;
if(v[k]==val) {
if(w[k]>1) {w[k]--;s[k]--;sum[k]-=val;return ;}
if(l[k]*r[k]==0) k=l[k]+r[k];
else if(rnd[r[k]]<rnd[l[k]])lturn(k),del(k,val);
else rturn(k),del(k,val);
}
else if(val>v[k]) {s[k]--;sum[k]-=val;del(r[k],val);}
else {s[k]--;sum[k]-=val;del(l[k],val);}
}
void find(int k,int rk)
{
if(k==0) return ;
if(rk<=s[l[k]]) {
sum2+=(sum[r[k]]+v[k]*w[k]);
find(l[k],rk);
}else if(rk>s[l[k]]+w[k]) {
sum1+=(sum[l[k]]+v[k]*w[k]);
find(r[k],rk-s[l[k]]-w[k]);
}else {
sum1+=(sum[l[k]]+(rk-s[l[k]]-1)*v[k]);
sum2+=(sum[r[k]]+(s[l[k]]+w[k]-rk)*v[k]);
tmp=v[k];
}
}
void getans()
{
sum1=sum2=0;
find(root,m);
ll sum=(m-1)*tmp-sum1+sum2-(K-m)*tmp;
if(sum<ans)ans=sum;
}
int main()
{
scanf("%d%d",&n,&K);m=((K+1)>>1);
fo(i,1,n) scanf("%lld",&h[i]);
for(int i=1;i<=K;i++)
insert(root,h[i]);
getans();
for(int i=K+1;i<=n;i++)
{
del(root,h[i-K]);
insert(root,h[i]);
getans();
}
printf("%lld",ans);
return 0;
}