bzoj1112: [POI2008]砖块Klo
2017-04-07 10:25
344 查看
链接
http://www.lydsy.com/JudgeOnline/problem.php?id=1112题解
看一下解的形式。你要选一段数,把他们都变成一个数字,假设变成的数字是x,那么你的代价是∑i=lr|ai−x|
这显然就是让你在数轴上找个点,到其它所有点的距离之和最小。这不是一个高中数学套路题吗?
直接取中位数不就好了。
那这个问题就成了查一个区间的中位数,还问你这个区间的每个数减去一个数的绝对值之和。
这不就是主席树吗?
代码
//主席树 #include <cstdio> #include <algorithm> #define maxn 100005 #define ll long long using namespace std; int N, ndtot, ans, K, tmp[maxn], h[maxn], lim=100000; struct segtree {int l, r, size;ll sum;segtree *ch[2];}pool[maxn*20], *root[maxn]; void ins(segtree *pre, segtree *now, int pos) { int mid=(pre->l+pre->r)>>1; *now=*pre; now->size++, now->sum+=tmp[pos]; if(now->l==now->r)return; if(pos<=mid)ins(pre->ch[0],now->ch[0]=pool+ ++ndtot,pos); else ins(pre->ch[1],now->ch[1]=pool+ ++ndtot,pos); } int kth(segtree *pre, segtree *now, int k) { if(now->l==now->r)return now->l; int s=now->ch[0]->size-pre->ch[0]->size; if(k<=s)return kth(pre->ch[0],now->ch[0],k); else return kth(pre->ch[1],now->ch[1],k-s); } ll segsum(segtree *pre, segtree *now, int l, int r) { if(l>r)return 0; int mid=(pre->l+pre->r)>>1; ll s=0; if(l<=pre->l and r>=pre->r)return now->sum-pre->sum; if(l<=mid)s+=segsum(pre->ch[0],now->ch[0],l,r); if(r>mid)s+=segsum(pre->ch[1],now->ch[1],l,r); return s; } int getsz(segtree *pre, segtree *now, int l, int r) { if(l>r)return 0; int mid=(pre->l+pre->r)>>1, s=0; if(l<=pre->l and r>=pre->r)return now->size-pre->size; if(l<=mid)s+=getsz(pre->ch[0],now->ch[0],l,r); if(r>mid)s+=getsz(pre->ch[1],now->ch[1],l,r); return s; } void build(segtree *p, int l, int r) { int mid=(l+r)>>1; p->l=l, p->r=r; if(l==r)return; build(p->ch[0]=pool+ ++ndtot,l,mid); build(p->ch[1]=pool+ ++ndtot,mid+1,r); } inline int read(int x=0) { char c=getchar(); while(c<48 or c>57)c=getchar(); while(c>=48 and c<=57)x=(x<<1)+(x<<3)+c-48,c=getchar(); return x; } void init() { int i; N=read(), K=read(); build(root[0]=pool+ ++ndtot,1,lim); for(i=1;i<=N;i++)tmp[i]=h[i]=read(); sort(tmp+1,tmp+N+1); for(i=1;i<=N;i++)h[i]=lower_bound(tmp+1,tmp+N+1,h[i])-tmp; for(i=1;i<=N;i++)ins(root[i-1],root[i]=pool+ ++ndtot,h[i]); } void work() { ll ans=(ll)1<<60, t; int i, x; for(i=K;i<=N;i++) { x=kth(root[i-K],root[i],K+1>>1); t=tmp[x]*getsz(root[i-K],root[i],1,x-1)-segsum(root[i-K],root[i],1,x-1) +segsum(root[i-K],root[i],x+1,lim)-tmp[x]*getsz(root[i-K],root[i],x+1,lim); ans=min(ans,t); } printf("%lld",ans); } int main() { init(); work(); return 0; }
相关文章推荐
- 【BZOJ1112】[POI2008]砖块Klo【Splay】
- BZOJ1112 [POI2008]砖块Klo
- 【BZOJ 1112】 [POI2008]砖块Klo
- bzoj1112 [POI2008] 砖块Klo
- BZOJ 1112: [POI2008]砖块Klo
- [bzoj1112][POI2008]砖块Klo
- BZOJ 1112 [POI2008]砖块Klo(可持久化线段树)
- bzoj1112 [POI2008]砖块Klo(平衡树/map/树状数组)
- BZOJ 1112: [POI2008]砖块Klo 线段树维护区间中位数
- BZOJ 1112: [POI2008]砖块Klo
- [主席树] BZOJ1112: [POI2008]砖块Klo
- 两道Splay小结--bzoj1112: [POI2008]砖块Klo&bzoj1588: [HNOI2002]营业额统计
- 【BZOJ1112】[POI2008]砖块Klo Treap
- BZOJ1112: [POI2008]砖块Klo
- [BZOJ1112][POI2008]砖块Klo(splay)
- BZOJ 1112: [POI2008]砖块Klo treap
- bzoj1112 [POI2008]砖块Klo
- 【枚举】【权值分块】bzoj1112 [POI2008]砖块Klo
- [Bzoj1112][POI2008]砖块Klo(splay)
- bzoj1112 [POI2008]砖块Klo