1. 程式人生 > 實用技巧 >題解 CF1437E 【Make It Increasing】

題解 CF1437E 【Make It Increasing】

題目連結

Solution CF1437E Make It Increasing

題目大意:給定一個序列,以及一些不能被修改的位置。問最少修改幾個數可以使得序列嚴格單調遞增。

dp


分析:

首先經典結論,把每個數減去它的下標,這樣我們就只需要使得序列單調不降就可以了,元素可以相同更方便一些。

最少修改幾個數,可以轉化為,我們要在序列中選取一個最長不下降子序列,修改其他位置的值。而那些不能被修改的位置,就是我們必須選入子序列的位置。

這樣我們沿用 \(nlogn\) 的經典做法,只不過稍加改動。設上一個欽定被選擇的位置為 \(pre\),下一個位置為 \(nxt\),那麼當前的位置 \(p\)

可能被選入子序列,當且僅當 \(val[pre] \leq val[p] \leq val[nxt]\)

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <vector>
#pragma GCC optmize(2)
using namespace std;
typedef long long ll;
constexpr int maxn = 5e5 + 100,inf = 0x7fffffff;
struct IO{//-std=c++11,with cstdio and cctype
	private:
		static constexpr int ibufsiz = 1 << 20;
		char ibuf[ibufsiz + 1],*inow = ibuf,*ied = ibuf;
		static constexpr int obufsiz = 1 << 20;
		char obuf[obufsiz + 1],*onow = obuf;
		const char *oed = obuf + obufsiz;
	public:
		inline char getchar(){
			#ifndef ONLINE_JUDGE
				return ::getchar();
			#else
				if(inow == ied){
					ied = ibuf + sizeof(char) * fread(ibuf,sizeof(char),ibufsiz,stdin);
					*ied = '\0';
					inow = ibuf;
				}
				return *inow++;
			#endif
		}
		template<typename T>
		inline void read(T &x){
			static bool flg;flg = 0;
			x = 0;char c = getchar();
			while(!isdigit(c))flg = c == '-' ? 1 : flg,c = getchar();
			while(isdigit(c))x = x * 10 + c - '0',c = getchar();
			if(flg)x = -x;
		}
		template <typename T,typename ...Y>
		inline void read(T &x,Y&... X){read(x);read(X...);}
		inline int readi(){static int res;read(res);return res;}
		inline long long readll(){static long long res;read(res);return res;}
		
		inline void flush(){
			fwrite(obuf,sizeof(char),onow - obuf,stdout);
			fflush(stdout);
			onow = obuf;
		}
		inline void putchar(char c){
			#ifndef ONLINE_JUDGE
				::putchar(c);
			#else
				*onow++ = c;
				if(onow == oed){
					fwrite(obuf,sizeof(char),obufsiz,stdout);
					onow = obuf;
				}
			#endif
		}
		template <typename T>
		inline void write(T x,char split = '\0'){
			static unsigned char buf[64];
			if(x < 0)putchar('-'),x = -x;
			int p = 0;
			do{
				buf[++p] = x % 10;
				x /= 10;
			}while(x);
			for(int i = p;i >= 1;i--)putchar(buf[i] + '0');
			if(split != '\0')putchar(split);
		}
		inline void lf(){putchar('\n');}
		~IO(){
			fwrite(obuf,sizeof(char),onow - obuf,stdout);
		}
}io;
template <typename A,typename B>
inline void chkmin(A &x,const B &y){if(y < x)x = y;}
template <typename A,typename B>
inline void chkmax(A &x,const B &y){if(y > x)x = y;}

int val[maxn],g[maxn],ans;
vector<int> pos;
int main(){
	const int n = io.readi(),k = io.readi();
	for(int i = 1;i <= n;i++)io.read(val[i]),val[i] -= i;
	pos.push_back(0);
	for(int i = 1;i <= k;i++)pos.push_back(io.readi());
	for(unsigned int i = 2;i < pos.size();i++)
		if(val[pos[i - 1]] > val[pos[i]])return io.write(-1,'\n'),0;
	pos.push_back(n + 1);
	val[0] = -inf;
	val[n + 1] = inf;
	memset(g,0x7f,sizeof(g));
	for(int i = 1;i <= n;i++){
		int nxt = *upper_bound(pos.begin(),pos.end(),i);
		int pre = *prev(lower_bound(pos.begin(),pos.end(),i));
		if(val[i] > val[nxt] || val[i] < val[pre])continue;
		int p = upper_bound(g + 1,g + n,val[i]) - g;
		if(nxt == n + 1)chkmax(ans,p);
		g[p] = val[i];
	}
	return io.write(n - ans,'\n'),0;
}