B. Quick Sort【Codeforces Round #842 (Div. 2)】
B. Quick Sort
You are given a permutation【排列】†
In one operation, you:
Choose
Remove them and then add them sorted in increasing order to the end of the permutation.
For example, if
Find the minimum number of operations needed to sort the permutation in increasing order【递增次序】. It can be proven that it is always possible to do so.
† A permutation of length
Input
The first line contains a single integer
The first line of each test case contains two integers
The second line of each test case contains
It is guaranteed that the sum of n over all test cases does not exceed
Output
For each test case output a single integer — the minimum number of operations needed to sort the permutation. It can be proven that it is always possible to do so.
Example
input
4
3 2
1 2 3
3 1
3 1 2
4 2
1 3 2 4
4 2
2 3 1 4
output
0
1
1
2
Note
In the first test case, the permutation is already sorted.
In the second test case, you can choose element
In the third test case, you can choose elements
In the fourth test case, it can be shown that it is impossible to sort the permutation in
简述题意
- 给出一个长度为
的不连续排列,通过每次移动 个数并排序放在排列的最后面,确保一定次数内一定可以使得排列正序,问最小操作数为几?
思路
- 如果需要最小化操作数,那么不需要移动的元素个数应该最大化,即找到{1,2,...}的maximal subsequence【最大子序列】的元素个数
- 我们可以在遍历过程中维护相对顺序来找到最大子序列的元素个数
- 结果是遍历一遍记录不满足相对顺序的个数除以每次可移动的个数向上取整
- 需要注意是:向上取整要先乘1.0,否则结果会先向下取整再向上取整
代码
点击查看代码
#include<iostream>
#include<cmath>
#define endl '\n'
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int k,t,n;
int a[N];
LL ans;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin >> t;
while(t -- ){
ans = 0;
cin >> n >> k;
for(int i = 1; i <= n; i ++)cin >> a[i];
int t = 0,m = 0;
for(int i = 1; i <= n; i ++){
if(a[i] != i - t){
m ++; //不满足相对顺序的数的个数
t ++; //维护相对顺序
}
}
cout << ceil(m * 1.0 / k) << endl; //注意:向上取整要先乘1.0,否则结果会先向下取整再向上取整
}
}
标准答案
点击查看代码
#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define allr(x) (x).rbegin(), (x).rend()
#define gsize(x) (int)((x).size())
const char nl = '\n'; //简写换行
typedef long long ll;
typedef long double ld;
using namespace std;
void solve() {
int n, k;
cin >> n >> k;
vector<int> p(n); //动态数组
for (int i = 0; i < n; i++) cin >> p[i];
int c_v = 1;
for (int i = 0; i < n; i++) {
if (p[i] == c_v) c_v++;
}
cout << (n - c_v + k) / k << nl;
}
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
cin >> T;
while (T--) solve();
}
解题历程
- 考虑了相对顺序但是结果计算方式错误
- AC(46 ms,3900 KB) 【00:57 - 01:29】 //二次思考
经验总结
- 向上取整要先乘1.0,否则结果会先向下取整再向上取整
- 注意如何维护相对顺序
- 不要盲目模拟过程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】