bzoj 1112: [POI2008]砖块Klo treap
2016-12-07 19:08
369 查看
题意
给出n个数,每次操作可以让一个数+1或-1,求连续的m个数,使得他们变成相同的数的操作数最少。n,m<=100000
分析
假设现在给出m个数,要想使得他们变成相同的数的操作数最少,显然要让他们都变成这个m个数的中位数。知道了这个后我们就可以用一棵treap来暴力这个m个值,然后每次查找中位数即可。
第一次用c++写treap,感觉好虚啊,顺便去借鉴了一波黄学长的删除操作。话说黄学长的代码真心简洁明了啊%%%
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define N 100005 #define ll long long using namespace std; int n,m,a ,size,tot,root; ll sum,ans; struct tree{int size,val,in,l,r,k;ll s;}t ; void updata(int x) { t[x].size=t[t[x].l].size+t[t[x].r].size+t[x].in; t[x].s=t[t[x].l].s+t[t[x].r].s+(ll)t[x].in*t[x].val; } void rttl(int &x) { int y=t[x].r; t[x].r=t[y].l; t[y].l=x; updata(x); updata(y); x=y; } void rttr(int &x) { int y=t[x].l; t[x].l=t[y].r; t[y].r=x; updata(x); updata(y); x=y; } void ins(int &x,int val) { if (!x) { x=++tot; t[x].val=t[x].s=val;t[x].size=t[x].in=1;t[x].k=rand(); return; } t[x].s+=val;t[x].size++; if (t[x].val==val) { t[x].in++; return; } if (val<t[x].val) { ins(t[x].l,val); if (t[t[x].l].k<t[x].k) rttr(x); }else { ins(t[x].r,val); if (t[t[x].r].k<t[x].k) rttl(x); } } void del(int &x,int val) { if (!x) return; if (t[x].val==val) { if (t[x].in>1) { t[x].in--;t[x].size--;t[x].s-=val;return; } else if (t[x].l*t[x].r==0) { x=t[x].l+t[x].r;return; } else if (t[t[x].l].k<t[t[x].r].k) { rttr(x);del(t[x].r,val); } else { rttl(x);del(t[x].l,val); } } else if (val<t[x].val) del(t[x].l,val); else del(t[x].r,val); updata(x); } int find(int x,int y) { if (t[t[x].l].size+1<=y&&t[t[x].l].size+t[x].in>=y) { sum+=t[t[x].l].s;size+=t[t[x].l].size; return t[x].val; } if (t[t[x].l].size+t[x].in<y) { sum+=t[t[x].l].s+(ll)t[x].val*t[x].in;size+=t[t[x].l].size+t[x].in; y-=t[t[x].l].size+t[x].in; return find(t[x].r,y); }else { return find(t[x].l,y); } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); t[0].k=1e7; for (int i=1;i<=m;i++) ins(root,a[i]); ll ans=1e17; sum=size=0; int x=find(root,(1+m)/2); ans=min(ans,(ll)x*size-sum+t[root].s-sum-(ll)x*(m-size)); for (int i=m+1;i<=n;i++) { del(root,a[i-m]); ins(root,a[i]); sum=size=0; int x=find(root,(1+m)/2); ans=min(ans,(ll)x*size-sum+t[root].s-sum-(ll)x*(m-size)); } printf("%lld",ans); return 0; }
相关文章推荐
- BZOJ 1112: [POI2008]砖块Klo treap
- BZOJ 1112 POI2008 砖块Klo Treap
- 【bzoj1112】[POI2008]砖块Klo Treap
- BZOJ 1112 [POI2008]砖块Klo Treap
- 【BZOJ1112】[POI2008]砖块Klo Treap
- BZOJ 1112 [POI2008]砖块Klo(可持久化线段树)
- 两道Splay小结--bzoj1112: [POI2008]砖块Klo&bzoj1588: [HNOI2002]营业额统计
- BZOJ 1112: [POI2008]砖块Klo
- [BZOJ 1112] [POI2008] 砖块Klo 【区间K大】
- BZOJ 1112: [POI2008]砖块Klo
- 【bzoj1112】[POI2008]砖块Klo
- 【bzoj1112】【poi2008】【砖块】【treap】
- BZOJ1112 - [POI2008]砖块Klo
- bzoj 1112: [POI2008]砖块Klo【对顶堆】
- BZOJ1112 [POI2008]砖块Klo
- BZOJ1112 - [POI2008]砖块Klo
- bzoj1112: [POI2008]砖块Klo
- bzoj 1112 [POI2008]砖块Klo
- [bzoj1112][POI2008]砖块Klo
- BZOJ1112: [POI2008]砖块Klo