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 2025-03-22 01:26  熙玺  阅读(38)  评论(0)    收藏  举报

Shu-How Zの小窝

Loading...