1715: 序列变换
时间限制: 1 Sec 内存限制: 128 MB
[提交][状态][讨论版]
题目描述
我们有一个数列A1,A2…An,你现在要求修改数量最少的元素,使得这个数列严格递增。其中无论是修改前还是修改后,每个元素都必须是整数。
请输出最少需要修改多少个元素。
输入
第一行输入一个N(1≤N≤10e5),表示数列的长度
第二行输入N个数A1,A2,…,An。
每一个数列中的元素都是正整数而且不超过10e6。
输出
输出最少需要修改多少个元素
样例输入
3
2 5 4
样例输出
1
提示
来源
/*
最长上升子序列的变形。
每个元素都必须为整数(正,负都行)
对于:
9
2 2 3 3 4 4 5 5 6
ans = 7
---->-1 2 3 4 5 6 7 8 9
当aj > ai 时,i < j,i与j之间的元素要也要严格递增,得满足这个条件:
aj-ai >= j-i
整理上式:
aj - j >= ai - i
所以可以对原序列预处理一下,nowValue = oldValue-index
然后本题数据比较大不呢之间用O(n^2)解法,只能用基于贪心的O(nlogn)解法
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int st[maxn];
int main()
{
ios::sync_with_stdio(false);
int n;
cin>>n;
for(int i = 0; i < n; i++)
{
cin>>a[i];
a[i] = a[i] - i;
}
int t = 0;
st[t] = -(1<<30);
for(int i = 0; i < n; i++)
{
// a[i] - a[j] >= i-j;-->a[i]-i >= a[j]-j,i>j
if(a[i] >= st[t])
{
st[++t] = a[i];
}
else
{
//可以直接用upper_bound,但是我更喜欢自己写二分
// int pos = upper_bound(st,st+t+1,a[i])-st;
//st[pos] = a[i];
int left = 1, right = t;
while(left <= right)
{
int mid = (left+right)>>1;
if(a[i] >= st[mid])
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
st[left] = a[i];
}
}
cout<<n-t<<endl;
return 0;
}