BZOJ 1112: [POI2008]砖块Klo
Time Limit: 10 Sec
Memory Limit: 162 MB
Submit: 1701
Solved: 597
题解:
对于一个长度为K的区间,把这个区间内的砖块的高度都变成中位数是最优的。
维护一个平衡树:保持只有K个节点,支持插入删除元素,同时维护子树节点个数、
子树权值和。
每次在树中查询第K/2大元素,同时计算权值比其大和权值比其小的所有节点的权值和
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
const LL N=100005;
const LL inf=1000000000000LL;
int n,K,a[N],root;
LL sum[N],w[N],v[N],ans=inf,now,tmp;
int siz[N],ls[N],rs[N],rnd[N];
void Pushup(LL x)
{
siz[x]=siz[ls[x]]+siz[rs[x]]+w[x];
sum[x]=sum[ls[x]]+sum[rs[x]]+w[x]*v[x];
}
void lx(int &x)
{
int t=rs[x];
rs[x]=ls[t],ls[t]=x;
Pushup(x),Pushup(t);
x=t;
}
void rx(int &x)
{
int t=ls[x];
ls[x]=rs[t],rs[t]=x;
Pushup(x),Pushup(t);
x=t;
}
int cnt;
void Ins(int &x,int p)
{
if(!x)
{
x=++cnt,v[x]=p,sum[x]=p,w[x]=1,siz[x]=1,rnd[x]=rand();
return;
}
if(v[x]==p) w[x]++;
else if(p<v[x]){Ins(ls[x],p);if(rnd[ls[x]]>rnd[x]) rx(x);}
else {Ins(rs[x],p);if(rnd[rs[x]]>rnd[x]) lx(x);}
Pushup(x);
}
void Del(int &x,int p)
{
if(v[x]==p)
{
if(w[x]>1) w[x]--;
else if(ls[x]*rs[x]==0) x=ls[x]+rs[x];
else if(rnd[ls[x]]<rnd[rs[x]]) lx(x),Del(x,p);
else rx(x),Del(x,p);
}
else if(p<v[x]) Del(ls[x],p);
else Del(rs[x],p);
Pushup(x);
}
void find(int x,int k)
{
if(k<=siz[ls[x]])
{
now+=sum[x]-sum[ls[x]];
find(ls[x],k);
}
else if(k<=siz[ls[x]]+w[x])
{
now+=sum[rs[x]]+(siz[ls[x]]+w[x]-k)*v[x];
now-=sum[ls[x]]+(k-siz[ls[x]])*v[x];
tmp=v[x];
return;
}
else
{
now-=sum[x]-sum[rs[x]];
find(rs[x],k-(siz[x]-siz[rs[x]]));
}
}
LL Query()
{
int pos=(K+1)>>1;
now=0;
find(root,pos);
return (pos*2-K)*tmp+now;
}
int main()
{
scanf("%d%d",&n,&K);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int j=1;
for(int i=1;j<=n;i++)
{
while(j<=n&&j<=i+K-1) Ins(root,a[j]),j++;
ans=min(ans,Query());
Del(root,a[i]);
}
printf("%lld",ans);
}
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
3
9
2
3
1
Sample Output
2
HINT
原题还要求输出结束状态时,每柱砖的高度.本题略去.