BZOJ1112: [POI2008]砖块Klo
Posted mt-li
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1112: [POI2008]砖块Klo相关的知识,希望对你有一定的参考价值。
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
今天考试时把这东西做出来还是挺开心的!
狗脑思考可得这东西还是中位数最佳。。
然后拍树状数组
代码如下:
#include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; typedef long long ll; int lowbit(int x){return x&-x;} ll c[2100000],s[2100000]; void change(ll x,ll d) { while(x<=1100000) { c[x]+=d; x+=lowbit(x); } } ll getshuliang(ll x) { ll sum=0; while(x!=0) { sum+=c[x]; x-=lowbit(x); } return sum; } ll getpaiming(ll sum) { ll x=0,now=0; for(ll i=(1ll<<22);i;i>>=1) { if(x+i<=1100000&&now+c[x+i]<sum) now+=c[x+i],x+=i; } ++x; return x; } void gai(ll x,ll d) { while(x<=1100000) { s[x]+=d; x+=lowbit(x); } } ll getsum(ll x) { ll sum=0ll; while(x) { sum+=s[x]; x-=lowbit(x); } return sum; } ll dd[1100000]; int n,k; ll a[110000]; int main() { freopen("akc.in","r",stdin); freopen("akc.out","w",stdout); ll ans=1ll<<61; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%lld",&a[i]),a[i]++; int pos=1; for(int i=1;i<k;i++)dd[a[i]]++,change(a[i],1),gai(a[i],a[i]); for(int i=k;i<=n;i++) { change(a[i],1),gai(a[i],a[i]);dd[a[i]]++; ll X; if(k%2==1)X=getpaiming(k/2+1); else X=(getpaiming(k/2)+getpaiming(k/2+1))/2; ll sum1=getsum(X-1),sum2=getsum(getpaiming(k))-sum1-dd[X]*X; ll geshu1=getshuliang(X-1),geshu2=k-geshu1-dd[X]; ans=min(ans,X*geshu1-sum1+sum2-X*geshu2); if(ans==0ll)break; change(a[pos],-1),gai(a[pos],-a[pos]);dd[a[pos]]--; pos++; } printf("%lld\n",ans); return 0; }
by_lmy
以上是关于BZOJ1112: [POI2008]砖块Klo的主要内容,如果未能解决你的问题,请参考以下文章