您的位置:首页 > 其它

BZOJ1112 [POI2008]砖块Klo

2015-04-05 14:04 225 查看
即求连续k个数的中位数。。。

我们维护两个堆,一个大根堆一个小根堆:

小根堆维护的是区间前一半大的数,大根堆维护的是区间后一半小的数,且小根堆中的所有数都比大根堆内所有数大

这样子中位数就是大根堆的堆顶元素 or 小根堆的堆顶元素 or 他们的平均数(貌似并没有区别QAQ)

每次区间移动一位的时候,把其中的一个数删去再加入一个数,保证两个堆的大小不变

所以我们需要维护两个堆,支持插入,定点删除

于是我用了平板电视= =

/**************************************************************
Problem: 1112
User: rausen
Language: C++
Result: Accepted
Time:868 ms
Memory:5900 kb
****************************************************************/

#include <cstdio>
#include <ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
const int N = 1e5 + 5;
const int int_inf = 1e9;
const ll ll_inf = (ll) 1e18;

struct data {
int v, w;
data() {}
data(int _v, int _w) : v(_v), w(_w) {}

inline bool operator < (const data &x) const {
return v < x.v;
}
inline bool operator > (const data &x) const {
return v > x.v;
}
};

typedef __gnu_pbds :: priority_queue <data, less <data>, pairing_heap_tag> min_heap;
typedef __gnu_pbds :: priority_queue <data, greater <data>, pairing_heap_tag> max_heap;

min_heap mnh;
min_heap :: point_iterator mnhw
;
max_heap mxh;
max_heap :: point_iterator mxhw
;
ll tot_mxh, tot_mnh;
int n, k, k1;
int a
;
ll ans;

inline int read() {
static int x;
static char ch;
x = 0, ch = getchar();
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
x = x * 10 + ch - '0', ch = getchar();
return x;
}

inline void insert_mx(int i) {
mxhw[i] = mxh.push(data(a[i], i));
tot_mxh += a[i];
}

inline void insert_mn(int i) {
mnhw[i] = mnh.push(data(a[i], i));
tot_mnh += a[i];
}

inline int pop_mx() {
static data tmp;
tmp = mxh.top(), mxh.pop();
tot_mxh -= tmp.v, mxhw[tmp.w] = NULL;
return tmp.w;
}

inline int pop_mn() {
static data tmp;
tmp = mnh.top(), mnh.pop();
tot_mnh -= tmp.v, mnhw[tmp.w] = NULL;
return tmp.w;
}

inline int delete_mx(int i) {
tot_mxh -= a[i];
mxh.modify(mxhw[i], data(0, i));
mxh.pop(), mxhw[i] = NULL;
}

inline int delete_mn(int i) {
tot_mnh -= a[i];
mnh.modify(mnhw[i], data(int_inf, i));
mnh.pop(), mnhw[i] = NULL;
}

#define mid mnh.top().v
inline ll calc_ans() {
return tot_mxh + 1ll * mid * (k - 2 * k1) - tot_mnh;
}
#undef mid

int main() {
int i, x, y;
n = read(), k = read(), k1 = k >> 1;
for (i = 1; i <= n; ++i) a[i] = read();
for (i = 1; i <= k; ++i)
insert_mx(i);
while (mxh.size() > k1)
i = pop_mx(), insert_mn(i);
ans = ll_inf;
for (i = k + 1; i <= n + 1; ++i) {
ans = min(ans, calc_ans());
if (i == n + 1) break;
if (mxhw[i - k] == NULL) delete_mn(i - k);
else delete_mx(i - k);
insert_mx(i);
while (mxh.size() && mnh.size() && mnh.top().v > mxh.top().v) {
x = pop_mx(), insert_mn(x);
x = pop_mn(), insert_mx(x);
}
while (mxh.size() > k1)
x = pop_mx(), insert_mn(x);
while (mxh.size() < k1)
x = pop_mn(), insert_mx(x);
}
printf("%lld\n", ans);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: