CF1223D Sequence Sorting(贪心)

给你一个序列a1,a2,…,an,由整数组成。

您可以将以下操作应用于此序列:选择某个整数x并将等于x的所有元素移到a的开头或结尾。请注意,您必须在一个操作中沿一个方向移动所有这些元素。

例如,如果a=[2,1,3,1,1,3,2],您可以在一次操作中获得以下序列(为方便起见,将等于x的元素表示为x元素):

[1,1,1,2,3,3,2]如果将所有1元素移到开头;

[2,3,3,2,1,1,1]如果将所有1元素移到末尾;

[2,2,1,3,1,1,3]如果将所有2个元素移到开头;

[1,3,1,1,3,2,2]如果将所有2个元素移到末尾;

[3,3,2,1,1,1,2]如果将所有3个元素移到开头;

[2,1,1,1,2,3,3]如果将所有3个元素移到末尾;

您必须确定此类操作的最小数量,以便序列a以非降序顺序排序。非降序意味着对于从2到n的所有i,满足条件ai-1≤ai。

请注意,您必须回答与q无关的查询。

题解:

/*
 * cf1223D
 * 题意:
 * 给出一个序列,有两种操作可以把所有相同的数组移动到队首或队尾,问最少操作几次可以保证这个序列是一个不递减的序列
 * 我们只需要记录一个元素的第一次出现的位置和最后一次出现的位置,然后记录有多少种不同的元素
 * 找到最长不递减子序列(仅包含不同的数),答案就是不同数的个数减去这个子序列的长度
 */

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+100;
int N,M;
int l[maxn];//记录第一次出现的位置
int r[maxn];//记录最后一次出现的位置
int a[maxn];
int main () {
    int T;
    scanf("%d",&T);
    while (T--) {
        scanf("%d",&N);
        for (int i=1;i<=N;i++) l[i]=0,r[i]=0;
        for (int i=1;i<=N;i++) {
            scanf("%d",&a[i]);
            if (!l[a[i]]) l[a[i]]=i;
            r[a[i]]=i;
        }
        int cnt=0;
        int last=0;
        int sum=0;
        int ans=0;
        for (int i=1;i<=N;i++) {
            if (l[i]) {
                if (last<l[i])
                    cnt++;
                else
                    cnt=1;
                ans=max(cnt,ans);
                sum++;
                last=r[i];
            }
        }
        printf("%d\n",sum-ans);
    }
}

猜你喜欢

转载自www.cnblogs.com/zhanglichen/p/12817759.html