codeforces 1437 E. Make It Increasing (最长上升子序列)

题目链接:https://codeforces.com/contest/1437/problem/E

我们发现,每个不能改的位置之间的块是互不影响的
所以我们考虑单独计算每个块内的答案

对于每个块,如果元素小于边界(左右两边不能修改的元素大小),那么是必须要修改的,
剩下的元素,我们要修改尽量少的元素
没错,就是序列长度减去最长上升子序列的数量

然而还有一个问题,最长上升子序列的某两个元素大小可能是相邻的,
但是对应到原序列中,可能这两个元素之间可能还有别的元素,这样就无法修改中间元素了

这里有一个小trick(看题解才明白): 如果最后 \(a[i]\) 是严格单调增的,那么 \(a[i] - i\) 一定是不降的,
所以可以令 \(c[i] = a[i] - i\),去求解 \(c[i]\) 的最长不降子序列,这样就可以保证选出的最长上升子序列之间的元素肯定可以改变

最后再判断一下什么时候无解就好了
时间复杂度\(O(nlogn)\)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 500010;

int n,k,cnt = 0; int inf; int ans;
int a[maxn],b[maxn],c[maxn],d[maxn],dp[maxn],g[maxn];

void DP(int l,int r){
	if(r<l) return;
	for(int i=l;i<=r;++i){
		if(c[i] <= c[r+1] && c[i] >= c[l-1]){
			int pos = upper_bound(dp + l, dp + r, c[i]) - dp;
			dp[pos] = c[i];	
		} 
	}
	int flag = 0;
	for(int i=r;i>=l;--i){
		if(dp[i] != inf){
			ans += (r - l + 1) - (i - l + 1);
			flag = 1;
			break;
		}
	}
	if(!flag) ans += r-l+1;
}

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }

int main(){
	ans = 0;
	memset(dp,0x3f,sizeof(dp));
	inf = dp[0];

	dp[0] = -inf;
	int flag = 0;
	n = read(), k = read();
	for(int i=1;i<=n;++i){
		a[i] = read();
		c[i] = a[i] - i;
	}
	
	c[0] = -inf; c[n+1] = inf;
	
	for(int i=1;i<=k;++i){
		b[i] = read();
		d[++cnt] = a[b[i]];
	}
	
	for(int i=1;i<=cnt;++i){
		int pos = lower_bound(dp + 1, dp + cnt, d[i]) - dp;
		dp[pos] = d[i];
	}
	if(dp[cnt] == inf){
		printf("-1\n");
	}
	else{
		int ff = 0;
		memset(dp,0x3f,sizeof(dp));
		dp[0] = -inf;
		
		for(int i=1;i<=k;++i){
			DP(b[i-1]+1,b[i]-1);
			if(i > 1 && b[i] - b[i-1] - 1 > 0 && b[i] - b[i-1] - 1 > a[b[i]] - a[b[i-1]] - 1){
				ff = 1;
				printf("-1\n");
				break;
			}
		}
		if(b[k] <= n - 1) DP(b[k]+1,n);
		if(!ff) printf("%d\n",ans);
	}
	
	return 0;
}
posted @ 2020-10-29 00:03  Tartarus_li  阅读(205)  评论(0编辑  收藏  举报