bzoj1112: [POI2008]砖块Klo
折腾我一中午。。
做法就是树状数组维护中位数。。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const int m=1001000; LL s[2][1100000]; int lowbit(int x){return x&-x;} void change(int x,int w,LL k) { while(x<=m) { s[w][x]+=k; x+=lowbit(x); } } LL getsum(int x,int w) { LL ret=0; while(x>0) { ret+=s[w][x]; x-=lowbit(x); } return ret; } int Bin[30]; int getrank(int k,int w) { int x=0,sum=0; for(int i=25;i>=0;i--) if(x+Bin[i]<=m&&sum+s[w][x+Bin[i]]<k) sum+=s[w][x+Bin[i]], x+=Bin[i]; x++; return x; } int a[110000]; int main() { freopen("klo.in","r",stdin); freopen("klo.out","w",stdout); Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2; int n,k; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]++; for(int i=1;i<k;i++) change(a[i],0,1), change(a[i],1,a[i]); LL ans=(1LL<<61); for(int r=k;r<=n;r++) { change(a[r],0,1), change(a[r],1,a[r]); int mid; if(k%2==1)mid=getrank(k/2+1,0); else mid=(getrank(k/2,0)+getrank(k/2+1,0))/2; LL c1=getsum(mid-1,0),c2=getsum(m,0)-getsum(mid,0); LL d1=getsum(mid-1,1),d2=getsum(m,1)-getsum(mid,1); ans=min(ans,(mid*c1-d1)+(d2-mid*c2)); int l=r-k+1; change(a[l],0,-1), change(a[l],1,-a[l]); } printf("%lld\n",ans); return 0; }
pain and happy in the cruel world.