[BZOJ1112][POI2008]砖块Klo
Posted xjr_01
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ1112][POI2008]砖块Klo相关的知识,希望对你有一定的参考价值。
[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的主要内容,如果未能解决你的问题,请参考以下文章