码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ1112][POI2008]砖块Klo

时间:2016-12-10 18:45:17      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:swap   type   span   text   sharp   维护   div   ota   class   

[BZOJ1112][POI2008]砖块Klo

试题描述

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

输入

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

输出

最小的动作次数

输入示例

5 3
3
9
2
3
1

输出示例

2

数据规模及约定

见“输入

题解

在滑动的区间内维护中位数以及 ∑比中位数大的数减中位数 和 ∑中位数减比中位数小的数。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
	return x * f;
}

#define maxn 100010
#define oo (1ll << 60)
#define LL long long
struct Node {
	int v, r, siz;
	LL sum;
	Node() {}
	Node(int _, int __): v(_), r(__) {}
} ns[maxn];
int ToT, rt, fa[maxn], ch[2][maxn];
void maintain(int o) {
	ns[o].siz = 1; ns[o].sum = ns[o].v;
	for(int i = 0; i < 2; i++) if(ch[i][o])
		ns[o].siz += ns[ch[i][o]].siz, ns[o].sum += ns[ch[i][o]].sum;
	return ;
}
void rotate(int u) {
	int y = fa[u], z = fa[y], l = 0, r = 1;
	if(z) ch[ch[1][z]==y][z] = u;
	if(ch[1][y] == u) swap(l, r);
	fa[u] = z; fa[y] = u; fa[ch[r][u]] = y;
	ch[l][y] = ch[r][u]; ch[r][u] = y;
	maintain(y); maintain(u);
	return ;
}
void insert(int& o, int v) {
	if(!o) {
		ns[o = ++ToT] = Node(v, rand());
		return maintain(o);
	}
	bool d = v > ns[o].v;
	insert(ch[d][o], v); fa[ch[d][o]] = o;
	if(ns[ch[d][o]].r > ns[o].r) {
		int t = ch[d][o];
		rotate(t); o = t;
	}
	return maintain(o);
}
void del(int& o, int v) {
	if(!o) return ;
	if(ns[o].v == v) {
		if(!ch[0][o] && !ch[1][o]) o = 0;
		else if(!ch[0][o]) {
			int t = ch[1][o]; fa[t] = fa[o]; o = t;
		}
		else if(!ch[1][o]) {
			int t  =ch[0][o]; fa[t] = fa[o]; o = t;
		}
		else {
			bool d = ns[ch[1][o]].r > ns[ch[0][o]].r;
			int t = ch[d][o]; rotate(t); o = t;
			del(ch[d^1][o], v);
		}
	}
	else {
		bool d = v > ns[o].v;
		del(ch[d][o], v);
	}
	return maintain(o);
}
int qkth(int o, int k) {
	if(!o) return -1;
	int ls = ch[0][o] ? ns[ch[0][o]].siz : 0;
	if(k == ls + 1) return ns[o].v;
	if(k > ls + 1) return qkth(ch[1][o], k - ls - 1);
	return qkth(ch[0][o], k);
}
LL lar(int o, int v) {
	if(!o) return 0;
	LL s = ch[1][o] ? ns[ch[1][o]].sum : 0;
	int ss = ch[1][o] ? ns[ch[1][o]].siz : 0;
	if(v < ns[o].v) return s + ns[o].v - (LL)(ss + 1) * v + lar(ch[0][o], v);
	return lar(ch[1][o], v);
}
LL sma(int o, int v) {
	if(!o) return 0;
	LL s = ch[0][o] ? ns[ch[0][o]].sum : 0;
	int ss = ch[0][o] ? ns[ch[0][o]].siz : 0;
	if(v > ns[o].v) return (LL)(ss + 1) * v - s - ns[o].v + sma(ch[1][o], v);
	return sma(ch[0][o], v);
}

int A[maxn];
int main() {
	int n = read(), k = read();
	for(int i = 1; i <= n; i++) A[i] = read();
	
	LL ans = oo;
	for(int i = 1; i <= k; i++) insert(rt, A[i]);
	int v = qkth(rt, (k >> 1) + 1);
//	printf("v: %d %lld\n", v, lar(rt, v) + sma(rt, v));
	ans = min(ans, lar(rt, v) + sma(rt, v));
	for(int i = k + 1; i <= n; i++) {
		insert(rt, A[i]); del(rt, A[i-k]);
		v = qkth(rt, (k >> 1) + 1);
//		printf("v: %d %lld\n", v, lar(rt, v) + sma(rt, v));
		ans = min(ans, lar(rt, v) + sma(rt, v));
	}
	
	printf("%lld\n", ans);
	
	return 0;
}

 

[BZOJ1112][POI2008]砖块Klo

标签:swap   type   span   text   sharp   维护   div   ota   class   

原文地址:http://www.cnblogs.com/xiao-ju-ruo-xjr/p/6156114.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!