原题链接

题意简述

给出一个n(n≤105)n(n \leq 10^5)个数的序列a(max{a}≤106)a(max\{a\}\leq10^6),每次给一个数+1/-1。求使得序列中存在连续k(k≤n)k(k \leq n)个相等的数至少要操作几次。

分析

题目实际上求的是|x1−h|+|x2−h|+...+|xk−h||x_1-h|+|x_2-h|+...+|x_k-h|的最小值,其中xx是aa的一个长度为kk的子串。
易知hh为序列xx的中位数时原式取得最小值,那我们的任务就是求区间中位数咯。

证明

记序列xx中小于hh的有c1c_1个,大于hh的有c2c_2个。
因为当hh增大Δh\Delta h,原式就增大Δh×c1−Δh×c2\Delta h \times c_1 - \Delta h \times c_2;
所以当c1<c2c_1时,hh越大原式越小;c1>c2c_1>c_2时,hh越大原式越大。
c1=c2c_1=c_2时原式取得最小值,此时hh为序列xx的中位数。

因为max{a}≤106max\{a\}\leq10^6可以开数组,我们用树状数组实现。
维护xx中小于等于ii的数的个数cnt[i]cnt[i],小于等于ii的数的和sum[i]sum[i]。首先通过二分找出中位数h0h_0,则原式的最小值为

h0×cnt[i]−sum[i]+h0×(k−cnt[i])×(Σxi−sum[i])

h_0 \times cnt[i]-sum[i] + h_0 \times (k-cnt[i]) \times (\Sigma{x_i}-sum[i])
总时间复杂度约为 O(nlog2max{a})O(nlog^2max\{a\})。

实现

开两个树状数组分别维护cnt[i],sum[i]cnt[i],sum[i]。

代码

//[POI2008]鐮栧潡Klo
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long lint;
int const N=1e5+10;
int const M=1e6+10;
lint const INF=1LL<<62;
int n,k,a[N];
int maxH; lint s[N];
lint tr[M],trs[M];
void add(int x,int f)
{int x1=x;while(x1<=maxH) tr[x1]+=f,x1+=x1&(-x1);x1=x;while(x1<=maxH) trs[x1]+=f*x,x1+=x1&(-x1);
}
lint sum1(int x)
{lint res=0;while(x>0) res+=tr[x],x-=x&(-x);return res;
}
lint sum2(int x)
{lint res=0;while(x>0) res+=trs[x],x-=x&(-x);return res;
}
lint sol(int fr)
{int L=0,R=maxH;while(L<R){int mid=(L+R)>>1;if(sum1(mid)<(k+1)/2) L=mid+1;else R=mid;}lint h=L,c1=sum1(h),c2=k-c1;lint s1=sum2(h),s2=s[fr+k-1]-s[fr-1]-s1;return (c1*h-s1)+(s2-c2*h);
}
int main()
{scanf("%d%d",&n,&k);for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]++;for(int i=1;i<=n;i++) maxH=max(maxH,a[i]);for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];lint ans=INF;for(int i=1;i<=k;i++) add(a[i],1);ans=min(ans,sol(1));for(int i=2;i<=n-k+1;i++){add(a[i-1],-1); add(a[i+k-1],1);ans=min(ans,sol(i));}printf("%lld",ans);return 0;
}

注意

要开long long
原数列中可能有0,先给全体+1s+1

BZOJ1112 - [POI2008]砖块Klo相关推荐

  1. bzoj1112[POI2008]砖块Klo*

    bzoj1112[POI2008]砖块Klo 题意: N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:丢掉某柱砖的一块砖.给某柱加上一块砖,现在希望用最小次数的动作完成任务.N≤1 ...

  2. BZOJ1112[POI2008]砖块Klo——非旋转treap

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

  3. 【主席树】bzoj1112: [POI2008]砖块Klo

    数据结构划一下水 Description N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. ...

  4. BZOJ1112: [POI2008]砖块Klo(洛谷P3466)

    平衡树 BZOJ题目传送门 洛谷题目传送门 动态维护中位数,平衡树上一发就好了. 代码: #include<cctype> #include<cstdio> #include& ...

  5. BZOJ1112: [POI2008]砖块Klo

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

  6. bzoj1112: [POI2008]砖块Klo(splay)

    题面在这里 做法 枚举每长度为 k k k 的段寻找中位数即可.splay维护. 代码 => 主要是想说这一点,由于计算的必要,相同的数不能合并到一个节点,否则之后调用 sum[ch[x][0] ...

  7. 1112: [POI2008]砖块Klo

    1112: [POI2008]砖块Klo Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1245  Solved: 426 [Submit][Sta ...

  8. [POI2008]砖块Klo

    1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2910 Solved: 1026 [Submit][Stat ...

  9. [POI2008] 砖块Klo

    洛谷 P3466 传送门 bzoj 1112 传送门 用treap维护一段长为k的区间即可. 先把1~k-1的都插入treap. 然后从k到n进行如下操作: 插入一个,计算,删除一个. 用到一个结论: ...

最新文章

  1. 无法用计算机名只能用ip访问局域网计算机,win10无法通过计算机名访问共享但能用IP的解决步骤...
  2. python while循环语句-Python While 循环语句
  3. /proc/xx/maps命令
  4. [笔记]画三角函数-涵盖画图基础
  5. 全球及中国抗甲状腺药物行业应用现状调研及未来产销需求预测报告2021-2027年
  6. 你选的那些创业方向 可能正在毁掉你!
  7. 推荐搜索炼丹笔记:向量召回 MIND多兴趣双塔模型
  8. 多版本JDK切换方式
  9. python3编程入门_在类Unix系统上开始Python3编程入门
  10. extjs中滚动条属性_前端学习随笔6 盒模型及相关属性
  11. 【Python】statsmodels.formula.api模块中ols参数的解释
  12. Intel Stratix10 Smart VID介绍以及使用
  13. Python新手入门“制造 贺卡”
  14. mysql添加字段语句
  15. Android 高德地图定位
  16. 单个JVM下支撑100w线程数vm.max_map_count
  17. 梅宏:学海无涯苦作舟
  18. 碟中谍5中的科技:详解“步态分析”
  19. AWS和Azure的区域
  20. yaf 修改php.ini,Yaf的配置

热门文章

  1. VPD-Forcing10年循环时间步长匹配问题
  2. R 语言实战-Part 4 笔记
  3. 连载《一个程序猿的生命周期》-《发展篇》 - 2.论团结在真正做事人身边的正确性
  4. JAVA入门基础6**(系列更新)———面向对象(二)的继承,抽象,接口
  5. redis微博——推模型
  6. 移动设备管理的具体措施有哪些?(上)
  7. 【毕业设计推荐】基于ssm易购云商城的设计与实现
  8. python基于PHP+MySQL的网上书店网上图书销售系统
  9. 云主机上传文件的具体步骤
  10. 斐讯N1安装Armbain Ubuntu教程