目录
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
二、解题报告
1、思路分析
2、复杂度
3、代码详解
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
Problem - 1575L - Codeforces
二、解题报告
1、思路分析
我们考虑最终 ai = i 所构成的 序列一定满足ai1 < ai2 < ai3……
且其在原数组中的下标也满足严格升序
我们不妨对原数组构造新数列(ai, i - ai),其中i >= ai
那么我们答案序列可以对应新数列的一个子序列,且满足
i1 - ai1 <= i2 - ai2 ……
这是显然的,因为题目的操作相当于把某段后缀前移一位,我们是通过把某些元素前移使其对应的,那么后面的元素的前移长度一定不小于前面元素的前移长度
于是我们只需要在新数列中找到最长的二维上升子序列
其中第一维严格上升,第二维非降序
这是个二维偏序问题,我们按照第一维排序,然后求第二维的最长非降序子序列即可
思考:我们求出的二维上升子序列满足元素在原数组下标升序吗
由于ai1 < ai2,i1 - ai1 <= i2 - ai2,二者相加,i1 < i2,故满足
2、复杂度
时间复杂度: O(nlogn)空间复杂度:O(n)
3、代码详解
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
const int N = 2e5 + 10;
int n, tot, res;
vector<int> p[N];
int main(){
//freopen("in.txt", "r", stdin);
cin >> n;
for(int i = 1, a; i <= n; i ++) {
cin >> a;
if(i >= a)
p[a].emplace_back(i - a);
}
vector<int> f;
for (int i = 1; i <= n; i ++){
sort(p[i].begin(), p[i].end());
reverse(p[i].begin(), p[i].end());
for(int x : p[i]){
auto it = upper_bound(f.begin(), f.end(), x);
if (it == f.end()) f.emplace_back(x);
else *it = x;
}
}
cout << f.size();
return 0;
}