[CF1437E] Make It Increasing(LIS)

原题

You are given an array of nn integers (a1, a2, ..., an), and a set bb of kk distinct integers from (1) to (n).

In one operation, you may choose two integers (i) and (x (1≤i≤n1≤i, x) can be any integer) and assign (ai:=x). This operation can be done only if ii does not belong to the set bb.

Calculate the minimum number of operations you should perform so the array aa is increasing (that is, (a_1<a_2<a_3<⋯<a_n)), or report that it is impossible.

Input

The first line contains two integers nn and (k (1≤n≤5⋅10^5, 0≤k≤n)) — the size of the array aa and the set bb, respectively.

The second line contains nn integers (a_1, a_2, ..., a_n (1≤a_i≤10^9)).

Then, if (k≠0), the third line follows, containing (k) integers (b_1, b_2, ..., b_k (1≤b_1<b_2<⋯<b_k≤n)). If k=0, this line is skipped.

Output

If it is impossible to make the array aa increasing using the given operations, print (−1).

Otherwise, print one integer — the minimum number of operations you have to perform.

Examples

input

7 2
1 2 1 1 3 5 1
3 5

output

4

input

3 3
1 3 2
1 2 3

output

-1

input

5 0
4 3 1 2 3

output

2

input

10 3
1 3 5 6 12 9 8 10 13 15
2 4 9

output

3

题意

对于一个序列,k个给定位置的数不能动,其它位置的数可以改成任意数,使其变成严格递增序列(前一个数不能等于后一个数)的最小改变次数。

思路

把序列根据给定的k位置,把序列分成k + 1个区间,对每个区间求最长严格递增子序列,并且每个选择的数不能小于左端点,不能大于右端点。区间长度减去当前区间最长严格递增子序列长度之和即最后的答案。

因为最后的序列要求严格递增,所以对于每个选进递增子序列的两个数,都要满足(a[r]- a[l] >= r-l), 移项得(a[r] - r >= a[l] - l), 所以对于每个a[i],预处理(a[i] = a[i] - i), 再对处理后的序列求满足条件的最长非递减子序列即可。求最长非递减子序列用O(nlogn)的做法。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f
#define PI 3.1415926535898
#define F first
#define S second
#define endl '
'
#define lson  rt << 1
#define rson  rt << 1 | 1
#define lowbit(x) (x &(-x))
#define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _per(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;

const int maxn = 5e5 + 7;
const int maxm = 1e3 + 7;
int n, k;
int a[maxn];
vector<int> v;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int x;
	cin >> n >> k;
	_rep(i, 1, n) cin >> a[i], a[i] -= i;
	v.push_back(0), a[0] = -inf;
	_rep(i, 1, k) {
		cin >> x;
		v.push_back(x);
	}
	v.push_back(n + 1), a[n + 1] = inf;
	f(i, 1, v.size()) {
		if (a[v[i]] < a[v[i - 1]]) {
			cout << -1 << endl;
			return 0;
		}
	}
	int ans = 0;
	f(i, 1, v.size()) {
		vector<int> tmp;
		int l = v[i - 1] + 1, r = v[i];
		_rep(j, l, r) {
			if (a[j] < a[l - 1] || a[j] > a[r]) continue;
			if (!tmp.size() || a[j] >= tmp[tmp.size() - 1]) tmp.push_back(a[j]);
			else {
				int pos = upper_bound(tmp.begin(), tmp.end(), a[j]) - tmp.begin();
				tmp[pos] = a[j];
			}
		}
		ans += r - l + 1 - tmp.size();
	}
	cout << ans << endl;

}
原文地址:https://www.cnblogs.com/hfcdyp/p/13897339.html