BZOJ 1112 [POI2008]砖块Klo Treap
来源:互联网 发布:流量监控软件排名 编辑:程序博客网 时间:2024/04/27 06:08
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
原题还要求输出结束状态时,每柱砖的高度.本题略去.
传送门
一个结论就是区间里面取中位数,总差值肯定最小。
画个数轴很容易证明出来的。
然后这题就变成了维护长度为k的区间的中位数,并且求出其它数和其差的绝对值之和。
可以用一个平衡树去搞,
维护结点的子树大小、子树sum;
然后求出所有比中位数小的,花费是中位数减去它们;
比中位数大的,花费是它们减去中位数。
每次区间变动,delete最前面的、insert最后面的即可。
明明打了重复结点看作一个点的做法……
竟然计算sum的时候总是漏点什么= =
话说treap真的比splay快好多= =
#include<bits/stdc++.h>#define ll long longusing namespace std;const int N=100005;int n,K,tot,root;int H[N];ll ans;struct Treap{int sz[N],occ[N],l[N],r[N],rnd[N];ll sum[N],val[N];void up(int &k){sz[k]=sz[l[k]]+sz[r[k]]+occ[k];sum[k]=sum[l[k]]+sum[r[k]]+val[k]*occ[k];}void rturn(int &k){int t=l[k];l[k]=r[t],r[t]=k;up(k),k=t,up(k);}void lturn(int &k){int t=r[k];r[k]=l[t],l[t]=k;up(k),k=t,up(k);}void insert(int &k,int x,int &tot){if (!k){k=++tot;sz[k]=occ[k]=1,l[k]=r[k]=0;sum[k]=val[k]=(ll)x,rnd[k]=rand();return;}sz[k]++,sum[k]+=(ll)x;if (x==val[k]){occ[k]++;return;}if (x<=val[k]){insert(l[k],x,tot);if (rnd[l[k]]<rnd[k]) rturn(k);} else{insert(r[k],x,tot);if (rnd[r[k]]<rnd[k]) lturn(k);}}void del(int &k,int x){if (!k) return;if (val[k]==x){if (occ[k]>1){sum[k]-=(ll)x,sz[k]--,occ[k]--;return;}if (!l[k] || !r[k]){k=l[k]^r[k];return;}if (rnd[l[k]]<rnd[r[k]]) rturn(k);else lturn(k);del(k,x);return;}sz[k]--,sum[k]-=(ll)x;if (x<=val[k]) del(l[k],x);else del(r[k],x);}ll SmallSum(int &k,int x){if (!k) return 0LL;if (val[k]<=x) return SmallSum(r[k],x)+sum[l[k]]+val[k]*occ[k];else return SmallSum(l[k],x);}ll BigSum(int &k,int x){if (!k) return 0LL;if (val[k]>x) return BigSum(l[k],x)+sum[r[k]]+val[k]*occ[k];else return BigSum(r[k],x);}int query_num(int &k,int x){if (!k) return 0;if (sz[l[k]]>=x) return query_num(l[k],x);if (sz[l[k]]+occ[k]<x) return query_num(r[k],x-sz[l[k]]-occ[k]);return val[k];}void query_pre(int &k,int x){if (!k) return;if (val[k]<=x){ans+=sz[l[k]]+occ[k],query_pre(r[k],x);}else query_pre(l[k],x);}void query_suc(int &k,int x){if (!k) return;if (val[k]>x){ans+=sz[r[k]]+occ[k],query_suc(l[k],x);}else query_suc(r[k],x);}}tr;int middle(){return tr.query_num(root,(K+1)>>1);}ll countans(int mid){ll tres;ans=0LL,tr.query_pre(root,mid);tres=ans*mid-tr.SmallSum(root,mid);ans=0LL,tr.query_suc(root,mid);tres+=tr.BigSum(root,mid)-ans*mid;return tres;}int main(){srand(283810);scanf("%d%d",&n,&K);for (int i=1;i<=n;i++) scanf("%d",&H[i]);tot=root=0;for (int i=1;i<=K;i++) tr.insert(root,H[i],tot);ll res=countans(middle());for (int i=K+1;i<=n;i++){tr.del(root,H[i-K]);tr.insert(root,H[i],tot);res=min(res,countans(middle()));}printf("%lld\n",res);return 0;}
阅读全文
0 0
- BZOJ 1112 POI2008 砖块Klo Treap
- BZOJ 1112 [POI2008]砖块Klo Treap
- bzoj 1112: [POI2008]砖块Klo treap
- 【BZOJ 1112】Poi2008砖块Klo treap
- BZOJ 1112: [POI2008]砖块Klo treap
- BZOJ 1112 [POI2008]砖块Klo Treap
- 【BZOJ 1112】 [POI2008]砖块Klo
- bzoj 1112 [POI2008]砖块Klo
- BZOJ1112: [POI2008]砖块Klo Treap
- bzoj 1112: [POI2008]砖块Klo(splay)
- 【BZOJ】1112 [POI2008]砖块Klo 平衡树
- 1112: [POI2008]砖块Klo
- 1112: [POI2008]砖块Klo
- BZOJ 1112: [POI2008]砖块Klo 线段树维护区间中位数
- BZOJ 1112: [POI2008]砖块Klo 平衡树,思维,枚举
- 【BZOJ】【P1112】【POI2008】【砖块Klo】【题解】【map】
- bzoj-1112 砖块Klo
- 1112: [POI2008]砖块Klo Splay+中位数
- xshell为什么连接不上ubuntu---could not connect to 'ip' (port 22): Connection failed.
- POJ 3469 Dual Core CPU(巧妙转化最大流)
- C++著名程序库的比较和学习经验
- python2抓取之反向登录获取session并持续访问抓取(iata网站为例)
- 进程间通信之select
- BZOJ 1112 [POI2008]砖块Klo Treap
- 设计模式10-桥接模式
- Lintcode133 Longest Words solution 题解
- 慕课网资料分享
- [k短路 && 可持久化堆]HDU5960.Subsequence
- zookeeper笔记02
- Activity面试题目整理
- 如何在centos环境下运行.exe文件
- Jquery设置(移除)disabled属性的方法