POI2008 KLO-ビルディングブロック

トピックポータル

死亡の原因:深刻ではない読書の問題


まず、我々は、長さの各セグメント列挙する暴力期待できる\(K \)間隔、この期間の間隔を、それが同じ高さでの操作の最小数の変更を求めるであろう。もちろん、我々は中央値の範囲を取るとき、最小回数と同じ高さにこのゾーン。

操作の数:
中央値よりも多い数のため、それらの中央値を減算することにより合計
の中央値数以下に、中央値は、その数だけ減算し、そのされている
最後の二つ要約することができます

だから我々はアクションがあるサポートする必要があります。

  1. この期間の中央値を求めて
  2. 数の中央値よりも少ない数を探しています
  3. 中央値よりも少ない数を探していると、

あなたは、私がもっと便利に重みツリーラインを使用するバランスの取れた木を、使用することができます。

最後に、ことに注意して高さを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;
}

おすすめ

転載: www.cnblogs.com/wxl-Ezio/p/11024478.html