题意

给一个长度为\(n\)的数组,你可以有两种操作

  • 将某一个数放置在数组开头
  • 将某一个数放置在数组结尾

问最小操作多少次可以得到一个非递减数列

(比\(F1\)难在\(n\)变大,且数组中元素可以有相同的)

分析

因为数组中的数很大,我们可以将其离散化然后操作,则\(a[i]\)为连续的整数,设\(tot\)种不同的数,则\(1\leq a[i] \leq tot\)

每个数最多操作一次,否则第一次可以不操作,那么我们就要找最多的不需要操作的数,如果不需要操作,则元素的位置不变,如果有这么一组不需要操作的数,我们可以发现,中间的数字是不能插进去的,所以这组数是在排序后仍相邻的数,则要找到最长的子序列,这个子序列在排序后仍然相邻,考虑以下几种情况

  • 这组数相同,则没有限制
  • 这组数中含有两种数,则要形如\(i,i,i,i+1,i+1\)这种形式,即排序后仍相邻
  • 这组数含有三种以上的数,即形如\(i,i,i+1,i+2,i+2,i+3\)这种形式,那么中间的数(\(i+1\),\(i+2\))一定是被取完了,否则其他的\(i+1\)或者\(i+2\)要插进去只能重新排序,与中间数字不能插进去不符,即这几个数并不是相邻,例如\(i,i+1,i+2,i+1\)这种序列,\(i,i+1,i+2\)并不满足条件,因为\(i+1\)并没取完

设\(dp[i][0]\)为只取相同的数且以\(a[i]\)为结尾所得到的最长子序列,\(dp[i][1]\)为\(a[i]\)还没取完且所得到的以\(a[i]\)为结尾最长子序列,\(dp[i][2]\)为\(a[i]\)取完且以\(a[i]\)为结尾所得到的最长子序列,我们用\(pos[i]\)表示数字\(i\)上次出现的位置,因为离散化了,所以数组可以满足,状态转移方程为(​\(r[a[i]]\)表示\(a[i]\)最后出现的位置,\(l[a[i]]\)表示\(a[i]\)最早出现的位置,\(num[a[i]]\)表示\(a[i]\)的个数,\(pos[a[i]]\)表示上一个\(a[i]\)出现的位置):

dp[i][0] = dp[pos[a[i]]][0] + 1;
dp[i][1] = max(dp[pos[a[i]]][1] + 1, max(dp[pos[a[i] - 1]][0] + 1, dp[pos[a[i] - 1]][2] + 1));
if (i == r[a[i]])
dp[i][2] = dp[l[a[i]]][1] + num[a[i]] - 1;
  • \(dp[i][0]\),方程表示上一个位置的\(a[i]\)接着取
  • \(dp[i][1]\),方程表示上一个\(a[i]\)接着取,或者上一个\(a[i]-1\)接着取,或者\(a[i]-1\)已经全部取完后接着取
  • \(dp[i][2]\),方程表示从最早出现的\(a[i]\)开始,后面都只取\(a[i]\)
#pragma GCC optimize(3, "Ofast", "inline")

#include <bits/stdc++.h>

#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define int ll
#define ls st<<1
#define rs st<<1|1
#define pii pair<int,int>
#define rep(z, x, y) for(int z=x;z<=y;++z)
#define com bool operator<(const node &b)
using namespace std;
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
const int maxn = (ll) 2e5 + 5;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
int T = 1;
int a[maxn], b[maxn];
int dp[maxn][3];
int l[maxn], r[maxn];
int pos[maxn], num[maxn]; void solve() {
int n;
cin >> n;
rep(i, 1, n)cin >> a[i], b[i] = a[i], dp[i][0] = dp[i][1] = dp[i][2] = 0, l[i] = r[i] = 0, num[i] = 0;
sort(b + 1, b + n + 1);
int tot = unique(b + 1, b + n + 1) - (b + 1);
rep(i, 1, n) {
a[i] = lower_bound(b + 1, b + tot + 1, a[i]) - b;
r[a[i]] = i;
if (!l[a[i]])
l[a[i]] = i, pos[a[i]] = i;
++num[a[i]];
}
int maxx = 1;
rep(i, 1, n) {
dp[i][0] = dp[pos[a[i]]][0] + 1;
dp[i][1] = max(dp[pos[a[i]]][1] + 1, max(dp[pos[a[i] - 1]][0] + 1, dp[pos[a[i] - 1]][2] + 1));
if (i == r[a[i]])
dp[i][2] = dp[l[a[i]]][1] + num[a[i]] - 1;
pos[a[i]] = i;
rep(j, 0, 2)maxx = max(maxx, dp[i][j]);
}
cout << n - maxx << '\n';
} signed main() {
start;
cin >> T;
while (T--)
solve();
return 0;
}

CodeForces 1367F2 Flying Sort (Hard Version)的更多相关文章

  1. Codeforces Round #650 (Div. 3) F1. Flying Sort (Easy Version) (离散化,贪心)

    题意:有一组数,每次操作可以将某个数移到头部或者尾部,问最少操作多少次使得这组数非递减. 题解:先离散化将每个数映射为排序后所对应的位置,然后贪心,求最长连续子序列的长度,那么最少的操作次数一定为\( ...

  2. codeforces 258div2 B Sort the Array

    题目链接:http://codeforces.com/contest/451/problem/B 解题报告:给出一个序列,要你判断这个序列能不能通过将其中某个子序列翻转使其成为升序的序列. 我的做法有 ...

  3. codeforces#1290E2 - Rotate Columns (hard version)(子集dp)

    题目链接: https://codeforces.com/contest/1209/problem/E2 题意: 给出$n$行和$m$列 每次操作循环挪动某列一次 可以执行无数次这样的操作 让每行最大 ...

  4. codeforces#1165 F2. Microtransactions (hard version) (二分+贪心)

    题目链接: https://codeforces.com/contest/1165/problem/F2 题意: 需要买$n$种物品,每种物品$k_i$个,每个物品需要两个硬币 每天获得一个硬币 有$ ...

  5. Codeforces 1326F2 - Wise Men (Hard Version)(FWT+整数划分)

    Codeforces 题目传送门 & 洛谷题目传送门 qwq 这题大约是二十来天前 AC 的罢,为何拖到此时才完成这篇题解,由此可见我是个名副其实的大鸽子( 这是我上 M 的那场我没切掉的 F ...

  6. codeforces 724B Batch Sort(暴力-列交换一次每行交换一次)

    题目链接:http://codeforces.com/problemset/problem/724/B 题目大意: 给出N*M矩阵,对于该矩阵有两种操作: (保证,每行输入的数是 1-m 之间的数且不 ...

  7. CodeForces 742B Batch Sort

    B. Batch Sort time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  8. quick sort java version

    import java.util.Random; public class test { public static void main(String[] args) { int[] arr= gen ...

  9. codeforces 340D Bubble Sort Graph(dp,LIS)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud  Bubble Sort Graph Iahub recently has lea ...

  10. Less or Equal CodeForces - 977C (sort+细节)

    You are given a sequence of integers of length nn and integer number kk. You should print any intege ...

随机推荐

  1. webpack Dev Server Invalid Options options should NOT have additional prop

    今日npm run serve时提示ERROR ValidationError: webpack Dev Server Invalid Options options should NOT have ...

  2. 不要轻易尝试 weexplus open as

    昨日使用 weexplust publish android 编译apk, 出现了一大堆错 FAILURE: Build failed with an exception. * What went w ...

  3. 解决echarts图形由于label过长导致文字显示不全问题

    使用echarts 打印饼图,在pc没问题,但一到移动端问题就来了,由于屏幕过小,导致label部分被遮挡 一.问题分析 如上图这个就尴尬了,囧么办呢? 还好echarts 提供了formatter方 ...

  4. 插件化工程R文件瘦身技术方案 | 京东云技术团队

    随着业务的发展及版本迭代,客户端工程中不断增加新的业务逻辑.引入新的资源,随之而来的问题就是安装包体积变大,前期各个业务模块通过无用资源删减.大图压缩或转上云.AB实验业务逻辑下线或其他手段在降低包体 ...

  5. 浅聊一下 C#程序的 内存映射文件 玩法

    一:背景 1. 讲故事 前段时间训练营里有朋友问 内存映射文件 是怎么玩的?说实话这东西理论我相信很多朋友都知道,就是将文件映射到进程的虚拟地址,说起来很容易,那如何让大家眼见为实呢?可能会难倒很多人 ...

  6. Educational Codeforces Round 150 (Rated for Div. 2) A-E

    比赛链接 A 代码 #include <bits/stdc++.h> using namespace std; using ll = long long; bool solve() { i ...

  7. jquery获取框值的数据,收藏一下吧

    效果图: html代码: <!DOCTYPE html> <html> <head> <title></title> <meta ch ...

  8. 基于DirectX11+ImGui的Win32桌面程序开发

    一.常见图形界面框架(DirectUI.GUI) 1.题外话,纯属扯O 举两个常用的开发框架,MFC和Qt Widget里面每个控件都是Window,这是和DirectUI最大的区别.下面简单梳理下这 ...

  9. 一文了解 io.LimitedReader类型

    1. 引言 io.LimitedReader 提供了一个有限的读取功能,能够手动设置最多从数据源最多读取的字节数.本文我们将从 io.LimitedReader 的基本定义出发,讲述其基本使用和实现原 ...

  10. 给程序员准备的“蜜糍”--SOD框架简介

    注:本文是SOD框架源码仓库的首页介绍,原文地址 一.框架介绍 1,SOD框架是什么? 以前有一个著名的国产化妆品"大宝SOD密",SOD框架虽然跟它没有什么关系,但是名字的确受到 ...