题目描述

N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.

输入

第一行给出N,K. (1 ≤ k ≤ n ≤ 100000), 下面N行,每行代表这柱砖的高度.0 ≤ hi ≤ 1000000

输出

最小的动作次数

样例输入

5 3
3
9
2
3
1

样例输出

2
 
考虑对于只有$k$个数的序列的最优解,显然是将所有数都变成中位数(因为如果变成的数比中位数小或者大都会有多于一半的数要改变)。
那么我们只需要维护出有$k$个连续数的序列,求出中位数并维护比中位数大的数的和及比中位数小的数的和即可得到这$k$个数的最优解,用平衡树维护即可。
对于$n$个数的序列只需要每次对连续$k$个数维护信息并求最优解然后取最小值即可。每次将第$i$个数删除,再将第$i+k$个数插入。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll ans;
int n,k;
int s[100010];
struct treap
{
treap *ls,*rs;
int size;
int val;
int rnd;
ll sum;
treap(){}
treap(treap *son,int v)
{
ls=rs=son;
size=1;
val=v;
sum=1ll*v;
rnd=rand();
}
void pushup()
{
sum=ls->sum+rs->sum+val;
size=ls->size+rs->size+1;
}
}tr[100010],nil;
typedef treap* node;
node root,null,cnt;
node a,b,c;
inline void init()
{
nil=treap(NULL,0);
null=&nil;
null->ls=null->rs=null;
null->size=0;
root=null;
cnt=tr;
}
inline node build(int v)
{
*cnt=treap(null,v);
return cnt++;
}
inline node merge(node x,node y)
{
if(x==null)
{
return y;
}
if(y==null)
{
return x;
}
if(x->rnd<y->rnd)
{
x->rs=merge(x->rs,y);
x->pushup();
return x;
}
else
{
y->ls=merge(x,y->ls);
y->pushup();
return y;
}
}
inline void split1(node rt,node &x,node &y,int k)
{
if(rt==null)
{
x=y=null;
return ;
}
if(rt->ls->size>=k)
{
y=rt;
split1(rt->ls,x,y->ls,k);
}
else
{
x=rt;
split1(rt->rs,x->rs,y,k-1-rt->ls->size);
}
rt->pushup();
}
inline void split2(node rt,node &x,node &y,int k)
{
if(rt==null)
{
x=y=null;
return ;
}
if(rt->val>=k)
{
y=rt;
split2(rt->ls,x,y->ls,k);
}
else
{
x=rt;
split2(rt->rs,x->rs,y,k);
}
rt->pushup();
}
inline void query()
{
split1(root,a,b,k/2);
split1(b,b,c,1);
ll res=1ll*a->size*b->val-a->sum;
res+=c->sum-1ll*c->size*b->val;
ans=min(res,ans);
root=merge(merge(a,b),c);
}
int main()
{
srand(12378);
scanf("%d%d",&n,&k);
ans=1ll<<60;
init();
for(int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
}
for(int i=1;i<=k;i++)
{
split2(root,a,b,s[i]);
root=merge(merge(a,build(s[i])),b);
}
query();
for(int i=k+1;i<=n;i++)
{
split2(root,a,b,s[i-k]);
split1(b,b,c,1);
root=merge(a,c);
split2(root,a,b,s[i]);
root=merge(merge(a,build(s[i])),b);
query();
}
printf("%lld",ans);
}

最新文章

  1. 伸缩盒子模型,旧的伸缩盒子模型。浏览器内核、css继承属性
  2. MySQL一些常用的时间函数
  3. 如何解决Mac与iPhone之间handoff连接问题
  4. python cx_Oracle install
  5. Apache的配置
  6. linux常用命令(5)rmdir命令
  7. Android的BUG(二) - SurfaceTexture中的野指针
  8. Error creating bean with name &amp;#39;com.you.user.dao.StudentDaoTest&amp;#39;: Injection of autowired dependencies
  9. WHM使用手册by lin
  10. ecos的app处理类
  11. RobotFramework下的http接口自动化Set Request Body 关键字的使用
  12. Scrapy框架
  13. Nginx处理请求的11个阶段(agentzh的Nginx 教程学习记录)
  14. Kafka笔记1(初步认识)
  15. Rhythmk 一步一步学 JAVA(6): JSP 语法学习笔记
  16. 数据库 Mysql 使用,优化,索引
  17. C++连接MySQL(Windows)
  18. jQuery警告/确认/提示弹出对话框效果(替换传统JavaScript下的提示框)
  19. gitlab使用外部的postgresql、外部的redis服务器
  20. new 关键字

热门文章

  1. 【春华秋实】.NET Core之只是多看了你一眼
  2. 基于ElasticStack数据分析应用系统
  3. C# NuGet包管理命令
  4. Java建造(Builder)模式
  5. Dynamics CRM项目实例之七:站点地图修改,联系人-订单-积分管理
  6. 第五篇Scrum冲刺博客
  7. WebStrom中实现Vue项目的快速启动
  8. Linux Mint chrome浏览器提示“需要安装adobe flash player”
  9. 智表ZCELL产品V1.4.0开发API接口文档 与 产品功能清单
  10. python selenium while 循环