Codeforces 1400E Clear the Multiset(貪心 + 分治)
阿新 • • 發佈:2020-08-27
連結:https://codeforces.com/problemset/problem/1400/E
來源:Codeforces
思路:給你一個數組,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零後操作的最少的次數。首先如果我們只使用操作 2,那麼一個區間內最多操作 \(r - l + 1\) 次。如果操作 1 和 操作 2 一起使用,我們可以貪心 + 分治的方式來求出操作次數,如果現在是一個區間,那麼我們找到區間內最小的值 \(cnt1\),此時我們進行操作操作 1 的次數就是 \(cnt1\),當前這個位置的數字就歸零了,此時這個數字左右兩邊還有可能進行重複的操作,那麼當前操作的次數就是 cnt1 + 左右兩邊區間可以操作的次數,這個時候我們需要和只進行操作 2 進行比較,判斷那種方式可以得到最小的操作次數。如果在遞迴的過程中最後只是剩下一個不為 0 的數字,那麼我們進行一次操作 2。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 5e3 + 10; int a[maxn]; int solve(int l, int r) { if(l > r) return 0; else if (l == r) { if(a[l] == 0) return 0; else return 1; } int cnt1 = 1e9 + 10, mid; for(int i = l; i <= r; ++ i) { if(a[i] < cnt1) { cnt1 = a[i]; mid = i; } } for(int i = l; i <= r; ++ i) a[i] -= cnt1; return min(cnt1 + solve(l, mid - 1) + solve(mid + 1, r), r - l + 1); } int main() { int n; scanf("%d", &n); for(int i = 1; i <= n; ++ i) scanf("%d", &a[i]); int ans = solve(1, n); printf("%d\n", ans); return 0; }