BZOJ1112: [POI2008]砖块Klo
Description
N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.
Input
第一行给出N,K. (1 ≤ k ≤ n ≤ 100000), 下面N行,每行代表这柱砖的高度.0 ≤ hi ≤ 1000000
Output
最小的动作次数
Sample Input
3
9
2
3
1
Sample Output
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相关推荐
- bzoj1112[POI2008]砖块Klo*
bzoj1112[POI2008]砖块Klo 题意: N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:丢掉某柱砖的一块砖.给某柱加上一块砖,现在希望用最小次数的动作完成任务.N≤1 ...
- BZOJ1112 - [POI2008]砖块Klo
原题链接 题意简述 给出一个n(n≤105)n(n \leq 10^5)个数的序列a(max{a}≤106)a(max\{a\}\leq10^6),每次给一个数+1/-1.求使得序列中存在连续k(k≤ ...
- BZOJ1112[POI2008]砖块Klo——非旋转treap
题目描述 N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任 ...
- 【主席树】bzoj1112: [POI2008]砖块Klo
数据结构划一下水 Description N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. ...
- BZOJ1112: [POI2008]砖块Klo(洛谷P3466)
平衡树 BZOJ题目传送门 洛谷题目传送门 动态维护中位数,平衡树上一发就好了. 代码: #include<cctype> #include<cstdio> #include& ...
- bzoj1112: [POI2008]砖块Klo(splay)
题面在这里 做法 枚举每长度为 k k k 的段寻找中位数即可.splay维护. 代码 => 主要是想说这一点,由于计算的必要,相同的数不能合并到一个节点,否则之后调用 sum[ch[x][0] ...
- 1112: [POI2008]砖块Klo
1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1245 Solved: 426 [Submit][Sta ...
- [POI2008]砖块Klo
1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2910 Solved: 1026 [Submit][Stat ...
- [POI2008] 砖块Klo
洛谷 P3466 传送门 bzoj 1112 传送门 用treap维护一段长为k的区间即可. 先把1~k-1的都插入treap. 然后从k到n进行如下操作: 插入一个,计算,删除一个. 用到一个结论: ...
最新文章
- 年薪75万的真实技术面试实践攻略(篇章二)
- java domain层_java框架中的controller层、dao层、domain层、service层、view层
- linux nexus状态,linux 启动 nexus
- android 图片圆角 遮罩_Android 自定义View练手Demo(一)实现圆角遮罩效果
- Python的线程/进程间通讯对象分析
- 微服务化之缓存的设计
- 对C#面向对象三大特性的一点总结
- 高可用MySQL架构设计2
- H.264(MPEG-4 AVC)级别(Level)、DPB 与 MaxDpbMbs 详解
- 打开php.ini中的Safe_mode,会影响哪些函数?
- AJAX+json+jquery实现预加载瀑布流布局
- C语言学习笔记---字符串转换函数
- 如何生成草料二维码在手机查看微信效果
- Linux 文本处理工具
- 项目三大文档: 项目章程, 初步的项目范围说明书 ,详细范围说明书,项目计划书
- 计算机考研山西大学和太原理工大学,山西大学和太原理工大学,山西省内的两所知名高校,哪所更强?...
- 使用EasyExcel的坑
- C#重点知识详解(转)
- 网站SEO优化做好能抵几个销售?看看杭州石炭纪怎么用网站来干了销售的活!
- 简单四步抓取腾讯视频MP4文件