[codeforces 1400| greedy | divede and conquer]E. Clear the Multiset

题目地址
题目思路:
对一个区间,只考虑2操作结果为(r - l + 1),加入1操作时,一定执行 t = min(al,al+1,al+2…,ar)次才能使结果最优化,对剩余区间不断执行以上操作,直至结果最优化。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define debug(x) cout<<#x<<" is "<<x<<endl
#define pb push_back
//#define dbg
const int N = 5000 + 5;
int a[N],n, l = -1,r;
vector<pair<int,int> > v;
ll ans = 0;
ll solve(int l,int r){
    
    

	if(l > r || l < 1 || r > n)return 0LL;
	if(l == r)return 1LL;
	int minn = INT_MAX;
	vector<int> zeros;
	for(int i = l;i <= r;i++){
    
    
		minn = min(a[i],minn);
	}
	for(int i = l;i <= r;i++){
    
    
		a[i] -= minn;
		if(a[i] == 0)
			zeros.pb(i);
	}

	ll res = minn;
	for(int i = 0;i < zeros.size();i++){
    
    
		int lpl = (i == 0)?l:zeros[i - 1] + 1;
		int lpr = zeros[i] - 1;
		res += solve(lpl,lpr);
		if(i == zeros.size() - 1){
    
    
			int rpl = zeros[i] + 1;
			int rpr = r;
			res += solve(rpl,rpr);
		} 
		#ifdef dbg
		debug(lpl);
		debug(lpr);
		#endif
	}
	return min(res,(long long)(r - l + 1));
}
int main(){
    
    
	scanf("%d",&n);
	for(int i = 1;i <= n;i++){
    
    
		scanf("%d",&a[i]);
		if(a[i] != 0){
    
    
			if(l == -1){
    
    
				l = r = i;
			}else r++;
		}else{
    
    
			v.pb(mp(l,r));
			l = -1;
		} 
	} 
	if(l != -1)v.pb(mp(l,r));
	for(int i = 0;i < v.size();i++){
    
    
		pair<int,int> p = v[i];
		l = p.fi,r = p.se;
		ans += solve(l,r);
		
	}
	cout<<ans<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_20252251/article/details/108291958