C. Min Max Sort
题目链接👈
题目描述🥰

题目思路😀
一个很明显也是不是那么明显的二分思维题。
这个题目我们明显可以逆向思考一下,最后我们是需要排好序的排列,如果数组已经排序,那么答案为0。否则,存在一个最后的操作,使排列变成1 2 3....n的形式。这意味着元素1和n被选为最后的操作(因为它们在操作后位于第一个和最后一个位置)。现在我们知道最后的操作是拿出1和n,这两个数字在排列中的具体位置并不重要,即我们可以假设答案增加了1,只考虑数字2 3 4 5....n-1。同样,对于“剩余”的排列,有两种选择,要么它已经排序,答案为1,要么存在最后的操作,使用数字2和n-1。如此往复,直到“剩余”的排列已排序或为空。
所以我们可以对操作次数 k-1进行二分
假设存在一个最大的k,使得段[k, n-k+1]内的元素在数组中下标是升序的。这意味着:
- 段内元素已排序:无需操作。
- 段外元素待处理:段外的元素分为两部分:
- 左边的1 2 ...k-1
- 右边的 n-k+2, ... n
这些段外元素需要通过k-1次操作逐步固定到正确位置,此时,段外的k-1对元素已全部固定,剩下的段[k, n-k+1]已排序,无需再操作。因此总操作次数为k-1
AC代码🧠
// Problem: C. Min Max Sort
// Contest: Codeforces - Educational Codeforces Round 142 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1792/problem/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define dev1(a) cout << #a << '=' << a << endl;
#define dev2(a, b) cout << #a << " = " << a << " " << #b << " = " << b << endl;
#define dev3(a, b, c) cout << #a << " = " << a << " " << #b << " = " << b << " " << #c << " = " << c << endl;
#define dev4(a, b, c, d) cout << #a << " = " << a << " " << #b << " = " << b << " " << #c << " = " << c << " " << #d << " = " << d << endl;
#define dev5(a, b, c, d, e) cout << #a << " = " << a << " " << #b << " = " << b << " " << #c << " = " << c << " " << #d << " = " << d << " " << #e << " = " << e << endl;
#define vec(a) \
for (int i = 0; i < a.size(); i++) \
cout << a[i] << ' '; \
cout << endl;
#define darr(a, _i, _n) \
cout << #a << ':'; \
for (int ij = _i; ij <= _n; ij++) \
cout << a[ij] << ' '; \
cout << endl;
#define cin(a,n) \
for(int i=0;i<n;i++) \
cin>>a[i];
#define endl "\n"
#define pow pim
int pim(int a,int k)
{
int res=1;
if(a==0)return 0;
while(k)
{
if(k&1)res=(int)res*a;
k>>=1;
a=(int)a*a;
}
return res;
}
#define fi first
#define se second
#define caseT \
int T; \
cin >> T; \
while (T--)
#define int long long
// #define int __int128
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 99999999;
// const int N = ;
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b)
{
return a * b / gcd(a, b);
}
string tf(string s,int num)
{
int _=(int)s.size();
for(int i=0;i<_;i++)s[i]=(s[i]-'a'+num)%26+'a';
return s;
}
int qmi(int a,int k,int mod){
int res=1;
while(k){
if(k&1) res=(int)res*a%mod;
a=(int)a*a%mod;
k>>=1;
}
return res;
}
inline int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
using i128 = __int128;
std::ostream &operator<<(std::ostream &os, i128 n) {
if (n == 0) return os << 0;
string s;
bool negative = false;
if (n < 0) {
negative = true;
n = -n;
}
while (n > 0) {
s += char('0' + n % 10);
n /= 10;
}
if (negative) os << '-';
reverse(s.begin(), s.end());
os << s;
return os;
}
std::istream& operator>>(std::istream& is, i128& n) {
string s;
is >> s;
n = 0;
int sign = 1;
if (!s.empty() && s[0] == '-') {
sign = -1;
s = s.substr(1);
}
for (char c : s) {
if (!isdigit(c)) {
is.setstate(ios::failbit);
return is;
}
n = n * 10 + (c - '0');
}
n *= sign;
return is;
}
i128 toi128(const std::string &s) {
i128 n = 0;
for (auto c : s) {
n = n * 10 + (c - '0');
}
return n;
}
i128 sqrti128(i128 n) {
i128 lo = 0, hi = 1E16;
while (lo < hi) {
i128 x = (lo + hi + 1) / 2;
if (x * x <= n) {
lo = x;
} else {
hi = x - 1;
}
}
return lo;
}
i128 gcd(i128 a, i128 b) {
while (b) {
a %= b;
std::swap(a, b);
}
return a;
}
void solve()
{
int n;
cin>>n;
vector<int>a(n+1);
for(int i=1;i<=n;i++)cin>>a[i];
int l=0,r=n/2;
auto check=[&](int mid)->bool{
int res=mid;
for(int i=1;i<=n;i++){
if(a[i]<mid+1||a[i]>n-mid)continue;
else{
if(a[i]-1!=res)return false;
else res=a[i];
}
}
return res==n-mid;
};
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}
cout<<l<<endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
caseT
solve();
return 0;
}
/*
*/
posted on
浙公网安备 33010602011771号