結果

問題 No.738 平らな農地
コンテスト
ユーザー 梧桐
提出日時 2026-02-23 20:03:35
言語 C++14
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++14 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
WA  
実行時間 -
コード長 2,770 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 1,654 ms
コンパイル使用メモリ 97,356 KB
実行使用メモリ 66,608 KB
最終ジャッジ日時 2026-02-23 20:03:52
合計ジャッジ時間 13,861 ms
ジャッジサーバーID
(参考情報)
judge4 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 5
other AC * 84 WA * 3
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp: In function 'int main()':
main.cpp:88:14: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17' [-Wc++17-extensions]
   88 |         auto [sum1, sz1] = sgt.Query(sgt.rt, 1, V, 1, mid - 1);
      |              ^
main.cpp:89:14: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17' [-Wc++17-extensions]
   89 |         auto [sum2, sz2] = sgt.Query(sgt.rt, 1, V, mid + 1, V);
      |              ^

ソースコード

diff #
raw source code

#include <iostream>
#include <cstdio>

using namespace std;

typedef long long LL;
typedef pair<LL, int> PLI;

const int N = 100010, V = 1000000000;
const LL INF = 9e18;

struct Node {
    int l, r, sz;
    LL sum;
};

int n, k, a[N];
LL ans;

// 动态开点权值线段树
// 每次求中位数,用树上二分

struct SegTree {
    int rt, idx;
    Node seg[N * 100];
    void PushUp(int u) {
        if (!seg[u].l) seg[u].l = ++idx;
        if (!seg[u].r) seg[u].r = ++idx;
        seg[u].sum = seg[seg[u].l].sum + seg[seg[u].r].sum;
        seg[u].sz = seg[seg[u].l].sz + seg[seg[u].r].sz;
    }
    void Add(int& u, int ul, int ur, int x, int v) {
        if (!u) u = ++idx;
        if (ul == ur) {
            seg[u].sz += v;
            seg[u].sum += x * v;
            return;
        }
        int mid = ul + ur >> 1;
        if (mid >= x) Add(seg[u].l, ul, mid, x, v);
        else Add(seg[u].r, mid + 1, ur, x, v);
        PushUp(u);
    }
    int Kth(int u, int ul, int ur, int kth) {
        if (ul == ur) return ul;
        int mid = ul + ur >> 1;
        if (seg[seg[u].l].sz >= kth) {
            return Kth(seg[u].l, ul, mid, kth);
        } else {
            return Kth(seg[u].r, mid + 1, ur, kth - seg[seg[u].l].sz);
        }
    }
    PLI Query(int u, int ul, int ur, int l, int r) {
        if (!u) return { 0LL, 0 };
        if (l <= ul && ur <= r) return { seg[u].sum, seg[u].sz };
        int mid = ul + ur >> 1;
        PLI ret = { 0LL, 0 };
        if (mid >= l) {
            PLI cur = Query(seg[u].l, ul, mid, l, r);
            ret.first += cur.first;
            ret.second += cur.second;
        }
        if (mid + 1 <= r) {
            PLI cur = Query(seg[u].r, mid + 1, ur, l, r);
            ret.first += cur.first;
            ret.second += cur.second;
        }
        return ret;
    }
};
SegTree sgt;

int main() {
    // freopen("farmland.in", "r", stdin);
    // freopen("farmland.out", "w", stdout);

    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);

    ans = INF;
    for (int i = 1; i <= k; ++i) sgt.Add(sgt.rt, 1, V, a[i], 1);
    for (int i = 1; i <= n - k + 1; ++i) {
        if (i >= 2) {
            sgt.Add(sgt.rt, 1, V, a[i - 1], -1);
            sgt.Add(sgt.rt, 1, V, a[i + k - 1], 1);
        }
        int mid = sgt.Kth(sgt.rt, 1, V, (k + 1) / 2);
        auto [sum1, sz1] = sgt.Query(sgt.rt, 1, V, 1, mid - 1);
        auto [sum2, sz2] = sgt.Query(sgt.rt, 1, V, mid + 1, V);
        if (sz1 == 0 && sz2 == 0) ans = min(ans, 0LL);
        else if (sz1 == 0) ans = min(ans, sum2 - sz2 * mid);
        else if (sz2 == 0) ans = min(ans, sz1 * mid - sum1);
        else ans = min(ans, (sz1 * mid - sum1) + (sum2 - sz2 * mid));
    }

    printf("%lld\n", ans);
    
    return 0;
}
0