Clear the Multiset
Problem Description
You have a multiset containing several integers. Initially, it contains a1a_1a1 elements equal to 1, a2a_2a2 elements equal to 2, …, ana_nan elements equal to n.
You may apply two types of operations:
- choose two integers lll and rrr (l≤rl≤rl≤r), then remove one occurrence of lll, one occurrence of l+1l+1l+1, …, one occurrence of rrr from the multiset. This operation can be applied only if each number from lll to rrr occurs at least once in the multiset;
- choose two integers iii and xxx (x≥1x≥1x≥1), then remove xxx occurrences of iii from the multiset. This operation can be applied only if the multiset contains at least xxx occurrences of iii.
What is the minimum number of operations required to delete all elements from the multiset?
Input
The first line contains one integer nnn (1≤n≤50001≤n≤50001≤n≤5000).
The second line contains n integers a1a_1a1, a2a_2a2, …, ana_nan (0≤ai≤1090≤a_i≤10^90≤ai≤109).
Output
Print one integer — the minimum number of operations required to delete all elements from the multiset.
Sample Input
4
1 4 1 1
Sample Output
2
题意
有一个多重集,其中值为iii的数字有aia_iai个(1≤i≤n)(1\le i \le n)(1≤i≤n)。可以进行两种操作:
- 选择两个数lll,r(l≤r)r(l\le r)r(l≤r),从集合删除值为lll到rrr的各删除一个。需保证lll到rrr中每种值至少有一个。
- 选择两个数i,xi,xi,x,从集合中删除xxx个值为iii的数。需保证当前集合中值为iii的数至少有xxx个。
求最少的操作次数使集合为空。
题解
只考虑操作2,所以最多需要n次操作。
设mi=min(a1,a2,...,an)mi = min(a_1, a_2, ..., a_n)mi=min(a1,a2,...,an).若要执行操作1,则一定是执行mi次l=1,r=nl=1,r=nl=1,r=n(若少于mi次,则实际上还是需要n次操作2,若多于mi次,则不符合条件)。
执行mi次操作后,剩下的ai>mia_i > miai>mi的则被分成若干段连续区间。对于每一段区间,递归处理,考虑其只需要使用操作2,或需要若干次操作1的最小操作数使集合为空。
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 5020;
const int mod = 1000000007;
int a[maxn];
int dfs(int l, int r, int up);
int main()
{
int n, m, i, j, k;
scanf("%d", &n);
for(i=1;i<=n;i++)
scanf("%d", &a[i]);
printf("%d", dfs(1, n, 0));
return 0;
}
int dfs(int l, int r, int up)
{
int mi = INF, i, j, sum;
for(i=l;i<=r;i++)
if(a[i] < mi)mi = a[i];
sum = mi-up, i = l;
while(i<=r){
if(a[i]>mi){
j=i;
while(a[j]>mi && j<=r)
j++;
sum += dfs(i, j-1, mi);
i = j;
}
else i++;
}
return min(sum, r-l+1);
}
本文探讨了CleartheMultiset算法问题,旨在通过两种操作清除包含特定数量整数的多重集。介绍了算法背景,详细解释了解决方案思路,包括如何通过操作减少元素,以及递归处理剩余元素的方法。

1万+

被折叠的 条评论
为什么被折叠?



