博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj1112 [POI2008]砖块Klo
阅读量:4606 次
发布时间:2019-06-09

本文共 2853 字,大约阅读时间需要 9 分钟。

 

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

Sample Output

2

HINT

原题还要求输出结束状态时,每柱砖的高度.本题略去.

 

很容易想到用个平衡树维护一段长为k的区间,每次区间右移就是加一个数再删一个数。

题意是把区间全变成一个数,然后求Σ|a[i]-x|

首先,把一段区间全变成中位数是最优的。这个可以自行脑补(一开始自己yy是平均数结果各种呵呵呵)

ndsf:splay好做啊

但是……总之我就是要用treap

求中位数x简单,第(k/2+1)大就是了(其实不太放心然后x+1再跑了一遍,其实不+1应该也没错吧……)

然后abs要分类讨论,要比它大的统计一次,比他小的统计一次

我的做法是直接自顶向下递归找一下,就是细节啦

以统计比它大的(upcalc(now,x))为例

递归搜到一个节点,如果这个点比它小,或者和它相等,那么左子树和这个点都不用统计,只要处理它的右子树就好了

如果这个点比它大,显然这个点和它的右子树都肯定比它大,直接推公式统计。左子树未定,递归搜下去

第一次写维护平衡树的sum就写疵了……各种不知道哪里写错……一怒之下treap节点几个变量改longlong结果A了……

#include
#include
#include
#define LL long longstruct treap{ int l,r,dat,rnd; LL rep,son; LL sum;}tree[500000];int a[100010];int n,k,treesize,root;LL tot,ans=1LL<<40;inline LL min(LL a,LL b){return a
tree[now].rnd)right_rotate(now); }else { insert(tree[now].r,x); if (tree[tree[now].r].rnd>tree[now].rnd)left_rotate(now); } update(now);}inline void del(int &now,int x){ if (!now)return; int num=tree[now].dat; if (x==num) { if (tree[now].rep>1) { tree[now].rep--; tree[now].son--; tree[now].sum-=tree[now].dat; return; } if (tree[now].l*tree[now].r==0)now=tree[now].l+tree[now].r; else { if (tree[tree[now].l].rnd>tree[tree[now].r].rnd) { right_rotate(now); del(now,x); }else { left_rotate(now); del(now,x); } } }else { tree[now].son--; if (x
tree[tree[now].l].son+tree[now].rep) return find(tree[now].r,x-tree[tree[now].l].son-tree[now].rep); else return tree[now].dat;}inline void upcalc(int now,int x){ if (!now)return; if (tree[now].dat<=x)upcalc(tree[now].r,x); else { tot+=(LL)(tree[now].sum-tree[tree[now].l].sum)-x*(tree[now].son-tree[tree[now].l].son); upcalc(tree[now].l,x); }}inline void dncalc(int now,int x){ if (!now)return; if (tree[now].dat>=x)dncalc(tree[now].l,x); else { tot+=(LL)x*(tree[now].son-tree[tree[now].r].son)-(tree[now].sum-tree[tree[now].r].sum); dncalc(tree[now].r,x); }}inline void calc(int now,int todel,int toadd){ if(todel!=toadd) { insert(root,toadd); del(root,todel); } int ave; ave=find(root,k/2+1); tot=0; upcalc(root,ave); dncalc(root,ave); ans=min(ans,tot); ave++; tot=0; upcalc(root,ave); dncalc(root,ave); ans=min(ans,tot);} inline LL read(){ LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}int main(){ n=read();k=read(); for(int i=1;i<=n;i++)a[i]=read(); for(int i=1;i<=k;i++)insert(root,a[i]); calc(k,0,0); for(int i=k+1;i<=n;i++)calc(i,a[i-k],a[i]); printf("%lld",ans);}

  

转载于:https://www.cnblogs.com/zhber/p/4035927.html

你可能感兴趣的文章
在线C++编译器
查看>>
C#中各种serialization的比较
查看>>
P2617 Dynamic Rankings
查看>>
工作学习常识1
查看>>
Linux小知识点
查看>>
VisualVM监控远程主机
查看>>
C#中检查网络是否连通的二种方法
查看>>
节假日设置
查看>>
<五>初探opengl,编写我们的镜头
查看>>
大数据操作:删除和去重
查看>>
2、JDBC-CURD
查看>>
【C语言零碎知识点】变量的存储类型
查看>>
编程时 对 用途这个字段定义时 不要用using 这个英文
查看>>
JQ实现accordion(可折叠)效果
查看>>
servlet的编码原理
查看>>
ARM4412的MMU内存管理单元
查看>>
HTML5可以存的东西有哪些:
查看>>
python相关遗漏知识点补充
查看>>
ReactJS实用技巧(2):从新人大坑——表单组件来看State
查看>>
无法删除数据库“XXX”,因为该数据库当前正在使用
查看>>