Sort Zero

Problem - C - Codeforces

 题目大意:

给定一个包含 n 个正整数 a1,a2,…,an 的数组。

在一项操作中,您可以执行以下操作:

选择任何整数 x。

对于所有使 ai=x 的 i,执行 ai:=0(将 0 分配给 ai)。

找到以非递减顺序对数组进行排序所需的最小操作数。


想法:

从后往前遍历数组,当第一次有 a[ i - 1] > a[ i ] 时,将1 ~ i - 1 之间的数全都清为0,过程中再将改变的数作st = true, 再从1开始将所有标记的数清为0,再重复一遍操作,这样可以保证得到的数组只有两种情况:(1)数组全为0,(2)数组前面一段为0,后一段为非递减数列;


 证明:

从后往前可以保证操作次数最少,

第一次操作可以保证数组前一段为0,后一段非递减,这样清为0之后可以保证后一段除了0的数是非递减的,

第二次操作之后直接可以保证前一段都为0,后一段的数都满足 a[ i - 1 ] <= a[ i ]


#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <climits>
using namespace std;
#define Bug return
#define Free 0
#define mst(x, y) memset(x, y, sizeof x)
#define X first
#define Y second
#define int long long
#define FAST ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 200010, INF = 0x3f3f3f3f;
const double EPS = 1e-6;
typedef pair<int, int> PII;
int T, n, idx;
int a[N];
bool st[N];
signed main()
{
    FAST;
    cin >> T;
    while (T--)
    {
        idx = 0;
        mst(st, false);

        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> a[i];

        for (int i = n; i > 1; i--)
        {
            if (a[i] < a[i - 1])
            {
                i--;
                while (i)
                {
                    if (!st[a[i]])
                    {
                        st[a[i]] = true;
                        idx++;
                    }
                    a[i] = 0;
                    i--;
                }
                break;
            }
        }
        for (int i = 1; i <= n; i++)
            if (st[a[i]])
                a[i] = 0;

        for (int i = n; i > 1; i--)
        {
            if (a[i] < a[i - 1])
            {
                i--;
                while (i)
                {
                    if (!st[a[i]] && a[i])
                    {
                        st[a[i]] = true;
                        idx++;
                    }
                    a[i] = 0;
                    i--;
                }
                break;
            }
        }
        cout << idx << endl;
    }

    Bug Free;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值