結果
| 問題 | No.738 平らな農地 | 
| コンテスト | |
| ユーザー |  kazuma | 
| 提出日時 | 2018-09-28 22:28:41 | 
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) | 
| 結果 | 
                                AC
                                 
                             | 
| 実行時間 | 918 ms / 2,000 ms | 
| コード長 | 5,158 bytes | 
| コンパイル時間 | 2,157 ms | 
| コンパイル使用メモリ | 213,816 KB | 
| 最終ジャッジ日時 | 2025-01-06 13:55:57 | 
| ジャッジサーバーID (参考情報) | judge3 / judge2 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| sample | AC * 5 | 
| other | AC * 87 | 
ソースコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
class fid {
	int n;
	vector<bool> data;
	vector<int> ra, se0, se1;
public:
	fid(int n_) : n(n_), data(n), ra(n + 1) {}
	void set(int i) {
		data[i] = true;
	}
	void build() {
		for (int i = 0; i < n; i++) {
			ra[i + 1] = ra[i] + data[i];
		}
		for (int i = 0; i < n; i++) {
			(data[i] ? se1 : se0).push_back(i);
		}
	}
	int rank(int i, bool b) const {
		return b ? ra[i] : i - ra[i];
	}
	int rank(int l, int r, bool b) const {
		return rank(r, b) - rank(l, b);
	}
	int select(int x, bool b) const {
		return (b ? se1 : se0)[x];
	}
	int select(int l, int x, bool b) const {
		return select(x + rank(l, b), b);
	}
};
template <typename T>
class wavelet_matrix {
	T h;
	int n;
	vector<fid> data;
	vector<int> mid;
	T get_h(T val) {
		T res = 1;
		while ((1LL << res) <= val) ++res;
		return res;
	}
public:
	wavelet_matrix(const vector<T>& data_)
		: h(get_h(*max_element(data_.begin(), data_.end()))), n(data_.size()), mid(h) {
		data.assign(h, n);
		vector<T> ar1(data_), ar2(n);
		for (T b = 0; b < h; b++) {
			int p = 0;
			for (int i = 0; i < n; i++) {
				if ((ar1[i] & ((T)1 << (h - 1 - b))) == 0) {
					ar2[p++] = ar1[i];
				}
			}
			mid[b] = p;
			for (int i = 0; i < n; i++) {
				if (ar1[i] & ((T)1 << (h - 1 - b))) {
					data[b].set(i);
					ar2[p++] = ar1[i];
				}
			}
			data[b].build();
			ar1.swap(ar2);
		}
	}
	int rank(int p, T val) {
		return rank(0, p, val);
	}
	int rank(int l, int r, T val) {
		if (val >> h) return 0;
		for (T b = 0; b < h; b++) {
			if (val & ((T)1 << (h - 1 - b))) {
				l = data[b].rank(l, true) + mid[b];
				r = data[b].rank(r, true) + mid[b];
			}
			else {
				l = data[b].rank(l, false);
				r = data[b].rank(r, false);
			}
		}
		return r - l;
	}
	int rank_less_than(int l, int r, T ub) {
		if (ub >> h) return r - l;
		int res = 0;
		for (T b = 0; b < h; b++) {
			bool d = (ub >> (h - 1 - b)) & 1;
			int lcnt = data[b].rank(l, d);
			int rcnt = data[b].rank(r, d);
			if (d) res += (r - l) - (rcnt - lcnt);
			l = lcnt;
			r = rcnt;
			if (d) {
				l += mid[b];
				r += mid[b];
			}
		}
		return res;
	}
	int rank_range(int l, int r, T lb, T ub) {
		return rank_less_than(l, r, ub) - rank_less_than(l, r, lb);
	}
	int select(int x, T val) {
		static int left[h];
		int l = 0, r = n;
		for (T b = 0; b < h; b++) {
			left[b] = l;
			if (val & ((T)1 << (h - 1 - b))) {
				l = data[b].rank(l, true) + mid[b];
				r = data[b].rank(r, true) + mid[b];
			}
			else {
				l = data[b].rank(l, false);
				r = data[b].rank(r, false);
			}
		}
		for (int b = h - 1; b >= 0; b--) {
			x = data[b].select(left[b], x, (bool)((val >> (h - 1 - b)) & 1)) - left[b];
		}
		return x;
	}
	int select(int l, int r, int x, T val) {
		return select(x + rank(l, val), val);
	}
	T kth_element(int l, int r, int k) {
		T res = 0;
		for (T b = 0; b < h; b++) {
			int cnt = data[b].rank(l, r, false);
			res <<= 1;
			if (k >= cnt) {
				l = data[b].rank(l, true) + mid[b];
				r = data[b].rank(r, true) + mid[b];
				k -= cnt;
				res |= 1;
			}
			else {
				l = data[b].rank(l, false);
				r = data[b].rank(r, false);
			}
		}
		return res;
	}
};
template <typename T>
class merge_tree {
	const int n;
	vector<vector<T>> data, sum;
	int size(int x) {
		int res = 1;
		while (res < x) res <<= 1;
		return res;
	}
	T query1(int node, T val) {
		int ub = lower_bound(data[node].begin(), data[node].end(), val) - data[node].begin();
		return sum[node][ub] - sum[node][0];
	}
	T query2(int node, T val) {
		int ub = lower_bound(data[node].begin(), data[node].end(), val) - data[node].begin();
		return sum[node].back() - sum[node][ub];
	}
public:
	merge_tree(const vector<T>& data_) : n(size(data_.size())), data(n * 2), sum(n * 2) {
		for (int i = 0; i < (int)data_.size(); i++)
			data[i + n].push_back(data_[i]);
		for (int i = n - 1; i >= 0; i--)
			merge(data[i * 2].begin(), data[i * 2].end(), data[i * 2 + 1].begin(), data[i * 2 + 1].end(), back_inserter(data[i]));
		for (int i = 0; i < n * 2; i++) {
			sum[i].assign(data[i].size() + 1, 0);
			for (int j = 0; j < (int)data[i].size(); j++) {
				sum[i][j + 1] = sum[i][j] + data[i][j];
			}
		}
	}
	T find1(int l, int r, T val) {
		l += n; r += n;
		T res = 0;
		while (l < r) {
			if (l & 1) res += query1(l++, val);
			if (r & 1) res += query1(--r, val);
			l >>= 1; r >>= 1;
		}
		return res;
	}
	T find2(int l, int r, T val) {
		l += n; r += n;
		T res = 0;
		while (l < r) {
			if (l & 1) res += query2(l++, val);
			if (r & 1) res += query2(--r, val);
			l >>= 1; r >>= 1;
		}
		return res;
	}
};
int main()
{
	int N, K;
	cin >> N >> K;
	vector<ll> A(N);
	for (int i = 0; i < N; i++) {
		cin >> A[i];
	}
	wavelet_matrix<ll> wm(A);
	merge_tree<ll> mt(A);
	ll res = LLONG_MAX;
	for (int i = 0; i + K <= N; i++) {
		ll lb = 1, ub = 1e9 + 1;
		while (ub - lb > 1) {
			ll c = (lb + ub) >> 1;
			if (wm.rank_less_than(i, i + K, c) < (K + 1) / 2) {
				lb = c;
			}
			else {
				ub = c;
			}
		}
		res = min(res, (wm.rank_less_than(i, i + K, lb) * lb - mt.find1(i, i + K, lb)) + (mt.find2(i, i + K, lb) - (ll)(K - wm.rank_less_than(i, i + K, lb)) * lb));
	}
	cout << res << endl;
	return 0;
}
            
            
            
        