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

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

Solution

问题可以这么描述为,求一个数x和一个区间[l...r],使\sum_{i=l}^{r}{x-a_i}最小。

容易想到的是这个x就是区间[l...r]的中位数。

那么现在就需要一个数据结构快速维护带插入删除的中位数,使用fhq-treap即可。

然后我的板子奇奇怪怪的需要一个虚点来当根所以中位数是k>>1+2...

注意要开longlong,以及,如果偷懒使用define int longlong的时候一定要在代码的最上方,至少要在读优的上方!!!!!!!!!!!!!!!!!

#include <bits/stdc++.h>#define ll long long
#define inf 0x7ffffffff
#define il inline
#define debug puts("233")
#define int long longnamespace io {#define in(a) a=read()#define out(a) write(a)#define outn(a) out(a),putchar('\n')#define I_int intinline I_int read() {I_int x = 0 , f = 1 ; char c = getchar() ;while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; }return x * f ;}char F[ 200 ] ;inline void write( I_int x ) {if( x == 0 ) { putchar( '0' ) ; return ; }I_int tmp = x > 0 ? x : -x ;if( x < 0 ) putchar( '-' ) ;int cnt = 0 ;while( tmp > 0 ) {F[ cnt ++ ] = tmp % 10 + '0' ;tmp /= 10 ;}while( cnt > 0 ) putchar( F[ -- cnt ] ) ;}#undef I_int}
using namespace io ;using namespace std ;#define N 100010int n , k , root = 1 ,tot = 0;
struct fhq {int siz , val , rnk , lc , rc , sum ;
}t[N];void up(int rt) { t[rt].siz = t[t[rt].lc].siz + t[t[rt].rc].siz + 1;t[rt].sum = t[t[rt].lc].sum + t[t[rt].rc].sum + t[rt].val;
}void split(int &a , int &b , int val , int rt) {if(!rt) {a = b = 0;return;}if(t[rt].val <= val) a = rt , split(t[a].rc , b , val , t[rt].rc) ;else b = rt , split(a , t[b].lc , val , t[rt].lc) ;up(rt);
}void merge(int a , int b , int &rt) {if(!a || !b) {rt = a + b;return;}if(t[a].rnk < t[b].rnk) rt = a , merge(t[a].rc , b , t[rt].rc) ;else rt = b , merge(a , t[b].lc , t[rt].lc) ;up(rt);
}int new_node(int val) {t[++tot] = (fhq) {1 , val , rand() , 0 , 0 , val} ;return tot ;
}void insert(int val) {int x = 0 , y = 0 , z = new_node(val) ;split(x , y , val - 1, root) ;merge(x , z , x) ; merge(x , y , root) ;
}void erase(int val) {int x = 0 , y = 0 , z = 0;split(x , y , val , root); split(x , z , val - 1 , x);merge(t[z].lc , t[z].rc , z) ; merge(x , z , x) ; merge(x , y , root) ;
}int find_kth(int rnk , int rt) {while(1) {if(t[t[rt].lc].siz + 1 < rnk) rnk -= t[t[rt].lc].siz + 1, rt = t[rt].rc;else if(t[t[rt].lc].siz >= rnk) rt = t[rt].lc ;else return t[rt].val; }
}void print(int rt) {if(t[rt].lc) print(t[rt].lc) ;cout<<t[rt].val<<" ";if(t[rt].rc) print(t[rt].rc) ;
}int query(int val) {int x = 0 , y = 0 , z = 0 ;split(x , y , val , root) ;split(x , z , val - 1 , x) ;int s1 = 1ll * (t[x].siz - 1)* val , s2 = 1ll * t[y].siz * val ;int a1 = t[x].sum , a2 = t[y].sum ;
//    cout<<a1<<" "<<a2<<" "<<endl;
    merge(x , z , x) ; merge(x , y , root) ;
//    cout<<s1-a1+a2-s2<<endl;return s1 - a1 - s2 + a2 ;
}int a[N] ;signed main() {
/*    freopen("1112.in","r",stdin);freopen("1112.out","w",stdout);*/srand((unsigned)time(0)) ;n = read() , k = read() ;new_node(0) ; t[1].siz = 0 ;for(int i = 1 ; i <= n ; i ++) a[i] = read() ;ll ans = 2e18 , M = 0 , L = 0 , R = 0; a[0] = 0;for(int i = 0 ; i < k ; i ++) insert(a[i]) ;int l = 0 , r = k - 1 ;while(r < n) {++l , ++r ;erase(a[l - 1]) ; insert(a[r]) ;int mid = find_kth((k>>1)+2 , root) ;ll tmp = query(mid) ;if(tmp < ans) {M = mid ; L = l ; R = r;ans = tmp;}
//        print(root);puts("");
//        cout<<l<< " "<<r<<" "<<mid<<endl;
    }outn(ans);
/*    for(int i = 1 ; i < L ; i ++) outn(a[i]) ;for(int i = L ; i <= R; i ++) outn(M) ;for(int i = R + 1 ; i <= n; i ++) outn(a[i]) ;*/return 0;
}

转载于:https://www.cnblogs.com/henry-1202/p/10092541.html

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

  1. bzoj1112[POI2008]砖块Klo*

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

  2. BZOJ1112 - [POI2008]砖块Klo

    原题链接 题意简述 给出一个n(n≤105)n(n \leq 10^5)个数的序列a(max{a}≤106)a(max\{a\}\leq10^6),每次给一个数+1/-1.求使得序列中存在连续k(k≤ ...

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

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

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

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

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

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

  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. 年薪75万的真实技术面试实践攻略(篇章二)
  2. java domain层_java框架中的controller层、dao层、domain层、service层、view层
  3. linux nexus状态,linux 启动 nexus
  4. android 图片圆角 遮罩_Android 自定义View练手Demo(一)实现圆角遮罩效果
  5. Python的线程/进程间通讯对象分析
  6. 微服务化之缓存的设计
  7. 对C#面向对象三大特性的一点总结
  8. 高可用MySQL架构设计2
  9. H.264(MPEG-4 AVC)级别(Level)、DPB 与 MaxDpbMbs 详解
  10. 打开php.ini中的Safe_mode,会影响哪些函数?
  11. AJAX+json+jquery实现预加载瀑布流布局
  12. C语言学习笔记---字符串转换函数
  13. 如何生成草料二维码在手机查看微信效果
  14. Linux 文本处理工具
  15. 项目三大文档: 项目章程, 初步的项目范围说明书 ,详细范围说明书,项目计划书
  16. 计算机考研山西大学和太原理工大学,山西大学和太原理工大学,山西省内的两所知名高校,哪所更强?...
  17. 使用EasyExcel的坑
  18. C#重点知识详解(转)
  19. 网站SEO优化做好能抵几个销售?看看杭州石炭纪怎么用网站来干了销售的活!
  20. 简单四步抓取腾讯视频MP4文件

热门文章

  1. 最新手机正则表达式验证
  2. 终于明白协方差的意义了
  3. 基于STM32寄存器版的嵌入式智慧仓库
  4. 远程桌面 重启关机等功能
  5. 机器人技术介绍(转载)
  6. 【博学谷学习记录】超强总结,用心分享 | 狂野大数据HDFS的JavaAPI操作~个人学习复习记录~PART-03
  7. CUDA版本的Locality-aware NMS
  8. 华为路由交换机常用命令
  9. 转转图书对基于Drools引擎的DMN实践
  10. 09 Marr算子(LoG算法)