cf E Make it increasing


题意:
题目大意:给出一个长度为 n 的序列,现在有 m 个位置被锁定,也就是无法进行操作,每次操作可以选择一个没有被锁定的位置,将其更改为任意数值,现在问最少进行多少次操作,可以使得整个序列变得严格递增
思路:
有个小技巧,看了大佬的博客才明白的,就是每一位都减去它的下标,这样判断起来,只需要判断锁住的元素是单调不下降的,就合法了,然后该题就转换成求k段操作数最少,由于每一段是独立的,那么考虑一段,有个结论最少操作数就是len-最长不下降子序列长度,那就分别求每一段就行了,加两个哨兵可以更有效的做题,然后在分别求每一段的时候也是不一样的,len=1的时候的数组是不能动的,最后一定要以a[r]结尾的最长不下降,lower_bound 和 upperbound把我搞糊涂了。。

#include<bits/stdc++.h>
using namespace std;
const int N=500010;
int d[N];
int n,m;
int a[N],b[N];
bool check()
{
	for(int i=2;i<=m;i++)
	{
		if(a[b[i]]<a[b[i-1]])
		return false;
	}
	return true;
}
int cal(int l,int r)
{
	int len=1;
	d[len]=a[l];
	for(int i=l+1;i<=r;i++)
	{
		if(a[i]>=d[len]) d[++len]=a[i];
		else
		{
			int pos=upper_bound(d+1,d+1+len,a[i])-d;
			if(pos!=1)
			d[pos]=a[i];
		}
	}
	int pos=upper_bound(d+1,d+1+len,a[r])-d-1;
	return (r-l+1)-pos;
}
int main()
{
	// int a[100]={0,1,2};
	//cout<<lower_bound(a,a+4,3)-a<<endl;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	cin>>a[i],a[i]-=i;
	for(int i=1;i<=m;i++)
	cin>>b[i];
	b[0]=0,b[m+1]=n+1;
	a[0]=-0x3f3f3f3f,a[n+1]=0x3f3f3f3f;
	if(!check())
	return 0*puts("-1");
	int res=0;
	for(int i=1;i<=m+1;i++)
	res+=cal(b[i-1],b[i]);
	cout<<res<<endl;
	return 0;
}

codeforce 文章被收录于专栏

写写cf的题解啥的

全部评论

相关推荐

贺兰星辰:不要漏个人信息,除了简历模板不太好以外你这个个人简介是不是太夸大了...
点赞 评论 收藏
分享
Hello_WordN:咱就是说,除了生命其他都是小事,希望面试官平安,希望各位平时也多注意安全
点赞 评论 收藏
分享
评论
点赞
1
分享
牛客网
牛客企业服务