POI2008 KLO-Building blocks

Topic Portal

Cause of death: not serious reading problems


First, we can expect violence to enumerate each segment of length \ (k \) interval, the interval for this period, it will seek changes to the minimum number of operations at the same height. Obviously, when we take the median range, this zone to the same height as the minimum number of times.

Number of operations:
for a number greater than the median, summed by subtracting the median number thereof
to the median number or less, the median is subtracted by the number thereof and their
last two can be summed

So we need to support actions are:

  1. Seeking this interval median
  2. Seeking a number less than the median number of
  3. Seeking a number less than the median and

You can use a balanced tree, where I use the weights tree line, more convenient.

Finally, note that the height can be 0

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define LL long long
#define ls p << 1
#define rs p << 1 | 1
#define mid ((l + r) >> 1)
using namespace std;
LL read() {
    LL k = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
      k = k * 10 + c - 48, c = getchar();
    return k * f;
}
LL a[100010], n, k, maxn, sum[100010];
struct zzz {
    LL cnt[1000010 << 2]; LL sum[1000010 << 2];
    void up(LL p) {
        cnt[p] = cnt[ls] + cnt[rs];
        sum[p] = sum[ls] + sum[rs];
    }
    void insert(LL x, LL p = 1, LL l = 0, LL r = maxn) {
        if(l == r) {
            ++cnt[p]; sum[p] += l;
            //cout << cnt[p] << ' ' << l << endl;
            return ;
        }
        if(x <= mid) insert(x, ls, l, mid);
        else insert(x, rs, mid+1, r);
        up(p);
    }
    void earse(LL x, LL p = 1, LL l = 0, LL r = maxn) {
        if(l == r) {
            --cnt[p]; sum[p] -= l; return ;
        }
        if(x <= mid) earse(x, ls, l, mid);
        else earse(x, rs, mid+1, r);
        up(p);
    }
    LL k_th(LL x, LL p = 1, LL l = 0, LL r = maxn) {
        if(l == r) return l;
        if(x <= cnt[ls]) return k_th(x, ls, l, mid);
        else return k_th(x - cnt[ls], rs, mid+1, r);
    }
    LL summ(LL nr, LL p = 1, LL l = 0, LL r = maxn, LL nl = 0) {
        LL ans = 0;
        if(nl <= l && nr >= r) return sum[p];
        if(nl <= mid) ans += summ(nr, ls, l, mid, nl);
        if(nr > mid) ans += summ(nr, rs, mid+1, r, nl);
        return ans;
    }
    LL numm(LL nr, LL p = 1, LL l = 0, LL r = maxn, LL nl = 0) {
        LL ans = 0;
        if(nl <= l && nr >= r) return cnt[p];
        if(nl <= mid) ans += numm(nr, ls, l, mid, nl);
        if(nr > mid) ans += numm(nr, rs, mid+1, r, nl);
        return ans;
    }
}tree;
int main() {
    n = read(), k = read();
    LL anss = -1, pos, num;
    for(LL i = 1; i <= n; ++i) a[i] = read(), maxn = max(a[i], maxn), sum[i] = a[i] + sum[i-1];
    for(LL i = 1; i <= n; ++i) {
        tree.insert(a[i]);
        if(i > k) tree.earse(a[i-k]);
        if(i >= k) {
            LL x = tree.k_th((k+1) >> 1);
            LL y = tree.summ(x), summ = sum[i] - sum[i-k], numl = tree.numm(x);
            //cout << y << ' ' << numl << ' ' << summ << endl;
            if(summ-y-x*(k-numl)+x*numl-y < anss || anss == -1) {
                anss = summ-y-x*(k-numl)+x*numl-y, pos = i; num = x;
            }
        }
    }
    printf("%lld\n", anss);
    
    for(LL i = 1; i <= n; ++i) {
        if(i >= pos-k+1 && i <= pos) {
            printf("%lld\n", num);
        }
        else printf("%lld\n", a[i]);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/wxl-Ezio/p/11024478.html