제출 #1331681

#제출 시각아이디문제언어결과실행 시간메모리
1331681shidou26K개의 묶음 (IZhO14_blocks)C++20
53 / 100
1096 ms31400 KiB
#include <bits/stdc++.h>
using namespace std;

typedef long long int64;

const int64 INF = 1e16 + 3;

struct SegmentTree {
	vector<int64> tree, lazy;
	SegmentTree (int n) : tree(n << 2 | 3, INF), lazy(n << 2 | 3, 0) {}

	void reload() {
		fill(tree.begin(), tree.end(), INF);
		fill(lazy.begin(), lazy.end(), 0);
	}

	void apply(int id, int64 x) {
		tree[id] += x;
		lazy[id] += x;
	}

	void push(int id) {
		if(lazy[id]) {
			apply(id << 1, lazy[id]);
			apply(id << 1 | 1, lazy[id]);
			lazy[id] = 0;
		}
	}

	void update(int id, int l, int r, int p, int64 x) {
		if(l == r) return tree[id] = x, void();
		int mid = (l + r) >> 1;
		push(id);
		if(p <= mid) update(id << 1, l, mid, p, x);
		else update(id << 1 | 1, mid + 1, r, p, x);
		tree[id] = min(tree[id << 1], tree[id << 1 | 1]);
	}

	void update(int id, int l, int r, int u, int v, int64 x) {
		if(r < u || v < l) return void();
		if(u <= l && r <= v) return apply(id, x), void();
		int mid = (l + r) >> 1;
		push(id);
		update(id << 1, l, mid, u, v, x);
		update(id << 1 | 1, mid + 1, r, u, v, x);
		tree[id] = min(tree[id << 1], tree[id << 1 | 1]);
	}

	int64 get(int id, int l, int r, int u, int v) {
		if(r < u || v < l) return INF;
		if(u <= l && r <= v) return tree[id];
		int mid = (l + r) >> 1;
		push(id);
		return min(get(id << 1, l, mid, u, v), get(id << 1 | 1, mid + 1, r, u, v));
	}
};

int main() {
	ios_base::sync_with_stdio(0); 
	cin.tie(0);

	int n, k; 
	cin >> n >> k;

	vector<int> nums(n + 1);
	for(int i = 1; i <= n; i++) {
		cin >> nums[i];
	}

	SegmentTree seg(n);
	vector<vector<int64>> dp(n + 1, vector<int64>(k + 1, INF));

	dp[0][0] = 0;
	for(int t = 1; t <= k; t++) {
		stack<int> mono;
		seg.reload();

		for(int i = 1; i <= n; i++) {
			seg.update(1, 1, n, i, dp[i - 1][t - 1]);
			while(!mono.empty() && nums[i] > nums[mono.top()]) {
				int p = mono.top(); mono.pop();
				seg.update(1, 1, n, (mono.empty() ? 0 : mono.top()) + 1, p, -nums[p]);
			}
			
			seg.update(1, 1, n, (mono.empty() ? 0 : mono.top()) + 1, i, nums[i]);
			mono.push(i);

			dp[i][t] = seg.get(1, 1, n, 1, i);
		}
	}

	cout << dp[n][k] << "\n";

	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...