逆向思维——cf1241D

/*
给定一个序列a,每次可以把值为x的所有元素放到a的首部或尾部,问将a变为lis的最少操作步数
对原序列离散化后重新打标记,
可以反着来考虑这个问题:即固定连续的元素值为[l,r]的点不动,那么剩下的所有元素值至多多进行一次操作,就可以让这个序列变成lis
所以求出这个最长合法的连续元素值段落即可 
*/
#include<bits/stdc++.h>
using namespace std;
#define N 300005
int n,a[N],b[N],L[N],R[N];

int main(){
    int t;cin>>t;
    while(t--){
        cin>>n;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];

        sort(b+1,b+1+n);
        int tot=unique(b+1,b+1+n)-b-1;
        
        
        for(int i=1;i<=tot;i++)
            L[i]=0x3f3f3f3f,R[i]=0; 
    
    
        for(int i=1;i<=n;i++){
            a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
            L[a[i]]=min(L[a[i]],i);
            R[a[i]]=max(R[a[i]],i);
        }
        
        
        int ans=0,last=0,len=0;
        for(int i=1;i<=tot;i++){
            if(L[i]>last){
                last=R[i];
                len++;
                ans=max(ans,len);
            }
            else {
                last=R[i];
                len=1;
                ans=max(ans,len);
            }
        }
        cout<<tot-ans<<'\n';
    }
} 

 

posted on 2019-10-17 16:32  zsben  阅读(163)  评论(0编辑  收藏  举报

导航