zoukankan      html  css  js  c++  java
  • CF1241 D Sequence Sorting(离散化+DP)

    题意

    给定数组a[n],用两种操作:

    1.将数组中所有值为x的数移至开头

    2.将数组中所有值为x的数移至末尾

    问,经过最少多少次操作,能将数组a[n]变为非递减的有序数列?

    (1<=n<=3e5,1<=a[i]<=n)

    思路:

    如果一个数全部分布在一段连续的区间上,那么可以不移动这个数。如果有好几个这样的连续的连续区间,且它们都是非递减的,那么这一个大区间内的数都可以不移动。因此只要求出最大的(所含数种类最多的)大区间,就能得到答案(只移动剩余的数)。

    将所有数离散化之后,记录每个数的最大下标和最小下标,之后实际上是一个最长上升子序列问题。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=3e5+5;
    int a[maxn],lisan[maxn];
    int dp[maxn],max1[maxn],min1[maxn];
    int main(){
        int q,n;
        cin>>q;
        while(q--){
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                lisan[i]=a[i];
            }
            sort(lisan+1,lisan+1+n);
            int len=unique(lisan+1,lisan+1+n)-(lisan+1);
            for(int i=1;i<=n;i++) a[i]=lower_bound(lisan+1,lisan+len+1,a[i])-lisan;
            for(int i=1;i<=n;i++){
                max1[a[i]]=i;
            }
            for(int i=n;i>=1;i--){
                min1[a[i]]=i;
            }
            int res=1;
            for(int i=1;i<=len;i++)
                dp[i]=1;
            for(int i=2;i<=len;i++){
                if(min1[i]>max1[i-1]){
                    dp[i]=dp[i-1]+1;
                }
                res=max(res,dp[i]);
            }
            int ans=len-res;
            printf("%d
    ",ans);
        }
    }
    
  • 相关阅读:
    深入理解加密、解密、数字签名和数字证书
    支付网关的设计
    spring boot Rabbitmq集成,延时消息队列实现
    五一之起一台服务器玩玩-u盘安装centos
    shell初识
    用户身份切换之初窥企业远程用户没root还有root权限
    man帮助文档打印
    开源镜像软件下载网址{转载}
    bash shell第一课
    jQuery常用ajax操作
  • 原文地址:https://www.cnblogs.com/ucprer/p/11685518.html
Copyright © 2011-2022 走看看