CF1400E - Clear the Multiset

CF1400E - Clear the Multiset

思路

昨天模拟赛考虑一道NOIP2018T1变形,不会。今天又偶遇一道变形,成功被昨天带偏,觉得肯定不是分治……

正解就是分治+贪心,每次选最小的群伤,然后分治到两边即可。

与 NOIP2018 不同的是整个区间 \([l, r]\) 也可以全部点杀掉,两种情况要取 \(\min\)

时间复杂度 \(O(n^2)\),瓶颈在预处理区间最小值。用 st 表可以做到 \(O(n \log n)\),用笛卡尔树可以做到 \(O(n)\)

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;
using ll = long long;
const int N = 5005;
int a[N], mi[N][N], n;
int cmin(int i, int j){
	if(a[i] < a[j]) return i;
	return j;
}
int solve(int l, int r, int val){
	if(l > r) return 0;
	if(l == r && a[l] > val) return 1;
	return min(r - l + 1, solve(l, mi[l][r] - 1, a[mi[l][r]]) + solve(mi[l][r] + 1, r, a[mi[l][r]]) + a[mi[l][r]] - val);
}
signed main(){
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> n;
	F(i, 1, n) cin >> a[i];
	F(i, 1, n){
		mi[i][i] = i;
		F(j, i + 1, n) mi[i][j] = cmin(mi[i][j - 1], j);
	}
	cout << solve(1, n, 0) << '\n';
	return fflush(0), 0;
}

总结

区间操作问题还是挺活的,还是说明得多积累经验。

posted @ 2024-11-27 09:43  superl61  阅读(9)  评论(0)    收藏  举报