Description
N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.
Input
第一行给出N,K. (1 ≤ k ≤ n ≤ 100000), 下面N行,每行代表这柱砖的高度.0 ≤ hi ≤ 1000000
Output
最小的动作次数
Sample Input
5 3
3
9
2
3
1
Sample Output
2
HINT
原题还要求输出结束状态时,每柱砖的高度.本题略去.
Source
平衡树维护一下找中位数
太久不写权值平衡树现在又已经快忘光了QAQ
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define GET (ch>='0'&&ch<='9')
#define MAXN 100010
#define LL long long
#define MAXLL 1ll<<60
#define MAXINT 0x3f3f3f3f
using namespace std;
int n,k,cnt,root;
int h[MAXN];
LL ans=MAXLL;
struct splay
{
int ch[2],fa,size,val;
LL sum;
}tree[MAXN];
void push_up(int x)
{
if (!x) return;
tree[x].size=tree[tree[x].ch[0]].size+tree[tree[x].ch[1]].size+1;
tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+tree[x].val;
}
void rot(int x,int &f)
{
int y=tree[x].fa,z=tree[y].fa,l,r;
l=(tree[y].ch[1]==x);r=l^1;
if (y==f) f=x;
else tree[z].ch[tree[z].ch[1]==y]=x;
tree[tree[x].ch[r]].fa=y;tree[y].fa=x;tree[x].fa=z;
tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;
push_up(y);push_up(x);
}
void Splay(int x,int &f)
{
while (x!=f)
{
int y=tree[x].fa,z=tree[y].fa;
if (y!=f)
{
if ((tree[y].ch[0]==x)^(tree[z].ch[0]==y)) rot(x,f);
else rot(y,f);
}
rot(x,f);
}
}
void insert(int val)
{
int i;
for (i=root;tree[i].ch[val>tree[i].val];i=tree[i].ch[val>tree[i].val]);
tree[i].ch[val>tree[i].val]=++cnt;tree[cnt].fa=i;
tree[cnt].val=tree[cnt].sum=val;tree[cnt].size=1;
Splay(cnt,root);
}
int find(int x,int k)
{
int l=tree[x].ch[0],r=tree[x].ch[1];
if (tree[l].size+1==k) return x;
if (tree[l].size>=k) return find(l,k);
return find(r,k-tree[l].size-1);
}
void del(int val)
{
int i,j;
for (i=root;tree[i].val!=val;i=tree[i].ch[val>tree[i].val]);
Splay(i,root);
if (!tree[root].ch[1]) {root=tree[root].ch[0];return;}
for (j=tree[root].ch[1];tree[j].ch[0];j=tree[j].ch[0]);
Splay(j,tree[root].ch[1]);
tree[j].ch[0]=tree[root].ch[0];tree[tree[root].ch[0]].fa=j;
tree[j].fa=0;root=j;push_up(j);
}
void in(int &x)
{
char ch=getchar();x=0;
while (!GET) ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();
}
int main()
{
in(n);in(k);
for (int i=1;i<=n;i++)
{
in(h[i]);insert(h[i]);
if (i>k) del(h[i-k]);
if (i>=k)
{
int x=find(root,(k+1)>>1);Splay(x,root);
int l=tree[x].ch[0],r=tree[x].ch[1];
ans=min(ans,tree[r].sum+(LL)tree[x].val*(tree[l].size-1)-tree[l].sum-(LL)tree[x].val*(tree[r].size-1));
}
}
cout<<ans<<endl;
}