1 条题解

  • 0
    @ 2021-11-19 8:55:44

    首先一个简单的想法,既然有 kk 个数无法操作,那么就相当于把序列分成了 k+1k+1 段,对于每一段,我们想让它变成单调上升的。

    一个做法是,所有值减去下标,这样就变成了单调不增子序列。

    直接对每一段区间跑一个最长单调不增子序列,其余都修改,就做完了。


    代码
    #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
    上传者