Problem 1567 - D - Sloth's Angry
Time Limit: 1000MS Memory Limit: 65536KB
Total Submit: 248 Accepted: 88 Special Judge: No
Total Submit: 248 Accepted: 88 Special Judge: No
Description
A forest is full of sloths, they are so eager for tree leaves and as a result, very angry.
We assume that the forest is a map of N * M grids, and each of the gird is an empty land or contains a big sloth. It’s guaranteed that the sequence of the sloth is a continuous segment from the leftmost
column for every row. ( You may consider that the number of columns M is infinite ).
As a sloth lover, you want to feed all the sloths as quick as possible. Every second you may select a rectangle area of the grids which only contains sloths and feed all the sloths there.
What’s the minimum time required to meet all the sloths’ needs in the forest?
Input
First line of each case contains one numbers N.(1≤ n ≤ 1 000).
The following line contains N numbers Ai, each describing the length of continuous sloths sequence from the left most column in every row. ( 1 <= Ai <= 10^9 )
The following line contains N numbers Ai, each describing the length of continuous sloths sequence from the left most column in every row. ( 1 <= Ai <= 10^9 )
Output
Output the answer on a single line for each case.
Sample Input
4
3 4 5 5
3 4 5 5
Sample Output
3
Hint
The distributing situation of the sloths in the sample is as follow:
SSS
SSSS
SSSSS
SSSSS
And you can choose three rectangles to cover it.
恩。很显然的贪心,证明如下:
设还未选择的子矩阵,即剩下的步骤中的最优解,组成了一个集合,每次尝试确定这个集合中左端点最小的一个矩阵,并把它从集合里删去。
这样我们可以发现,某行树懒是否被完全喂饱,取决于当前选择的矩阵是否包含该行的最右边的端点。换句话说,如果不包含这个最右边的端点,那么我们称这次的操作对该行树懒并不产生实质影响。
如此,显然可以得到一个贪心策略:每次选择整个区间中每行右端点中最小的值,并利用一次操作去掉这些行。然后继续划分下去。
#include<algorithm>
#include<iostream>
#include<limits.h>
#include<stdlib.h>
#include<string.h>
#include<cstring>
#include<iomanip>
#include<stdio.h>
#include<bitset>
#include<cctype>
#include<math.h>
#include<string>
#include<time.h>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<list>
#include<map>
#include<set>
#define LL long long
using namespace std;
const LL mod = 1e9 + 7;
const double PI = acos(-1.0);
const int M = 1005;
int a[M];
LL work(int l, int r, int x)
{
int last = l, mn = a[l];
LL len = r - l + 1, sum;
for(int i = l; i <= r; ++i)
mn = min(mn,a[i]);
sum = 1;
for(int i = l; i <= r; ++i){
if(a[i] == mn){
if(last < i)
sum += work(last,i - 1,mn);
last = i + 1;
}
}
if(last <= r)
sum += work(last,r,mn);
return min(len,sum);
}
int main()
{
int n;
while( cin >> n ){
for(int i = 1; i <= n; ++i)
scanf("%d",&a[i]);
int flag = 2;
for(int i = 2; i <= n; ++i){
if(a[i] == a[i - 1])
continue;
a[flag++] = a[i];
}
LL ans = work(1,flag - 1,0);
cout << ans << endl;
}
return 0;
}