1 条题解
-
0
首先一个简单的想法,既然有 个数无法操作,那么就相当于把序列分成了 段,对于每一段,我们想让它变成单调上升的。
一个做法是,所有值减去下标,这样就变成了单调不增子序列。
直接对每一段区间跑一个最长单调不增子序列,其余都修改,就做完了。
代码
#include<bits/stdc++.h> using namespace std; const int N=5e5+5; int n,k,a[N],p[N],ff,b[N],c[N]; void add(int x,int y){for(;x<=n;x+=x&-x)c[x]=max(c[x],y);} int ask(int x){int ans=0;for(;x;x-=x&-x)ans=max(ans,c[x]);return ans;} void clear(int x){for(;x<=n;x+=x&-x)c[x]=0;} int main() { int ans=0; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]-=i,p[i]=a[i]; for(int i=1;i<=k;i++)scanf("%d",&b[i]); sort(p+1,p+n+1); for(int i=1;i<=n;i++)a[i]=lower_bound(p+1,p+n+1,a[i])-p;//离散化 a[0]=0,a[n+1]=n+1; b[0]=0,b[k+1]=n+1; for(int i=1;i<=k+1;i++){ if(a[b[i]]<a[b[i-1]]){ ff=1; break; } int maxx=0; for(int j=b[i-1]+1;j<b[i];j++){ if(a[j]>=a[b[i-1]]&&a[j]<=a[b[i]]){//必须在左右数的区间中才可以 int t=ask(a[j])+1; maxx=max(maxx,t); add(a[j],t); } } for(int j=b[i-1]+1;j<b[i];j++)clear(a[j]); ans+=maxx; } if(ff)puts("-1"); else printf("%d",n-(k+ans)); return 0; }
- 1
信息
- ID
- 11
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者