题解
解法一:贪心 + 二分法
此题为LIS的进阶题,可参考https://blog.csdn.net/weixin_53526046/article/details/128688062
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10; //柱子的最大测试数量
int n;
int a[N], b[N];
int main()
{
cin >> n;
for (int i = 1; i <= n; ++ i )
cin >> a[i];
reverse(a + 1, a + n + 1);
for (int i = 1; i <= n; i ++ )
a[i] -= i;
int k = 1; //k代表不合题意的数据个数
while (a[k] < 0) //找到值不为0的某元素的下标(因为水管高度一定大于等于1,所以这一步骤可去除,不影响)
k ++;
//核心代码
int len = 0; //len代表 b数组的长度
b[++ len] = a[k];
for (int i = k + 1; i <= n; ++ i ){
if (a[i] >= b[len]){ //一定要大于等于,因为 a[i] 等于 b[len] 说明后一个数大于前一个数,可以取
len++;
b[len] = a[i];
}
//为保证子序列严格递增,所求的每一个元素需大于等于该元素所在的下标值
else if (a[i] >= 0){
//在 数组b 中寻找第一个大于 a[i] 的元素所在下标
int index = upper_bound(b + 1, b + len + 1, a[i]) - b;
b[index] = a[i];
}
}
//改变柱子的最少次数 = 柱子的数量 - LIS
cout << n - len - k + 1 << endl;
return 0;
}