【排序】

【排序】

本条博客仅收入纯排序相关的题目

【推公式】Transmission Mission

https://atcoder.jp/contests/abc414/tasks/abc414_d

题目大意

image

思路

首先排序位置
如果最开始只有一个基站:只能建在最中间,且信号强度为x[n]-x[1]
给数组分成*(m-1)段*
假设在第j个点分段:
信号强度为 x[j]-x[1] + x[n]-x[j+1]
->化为(x[n]-x[1]) - (x[j+1]-x[j])
->每次分段都会使答案减少(x[j+1]-x[j])
->求最小答案:枚举x[i]-x[i-1],找前m-1个即可

代码

int n,m;
void solve(){
    cin>>n>>m;
	vector<i64> x(n+1,0);
	for(int i=1;i<=n;i++) cin>>x[i];
	sort(x.begin()+1,x.end(),cmp64);
	vector<i64> pos;
	for(int i=2;i<=n;i++){
		pos.push_back(x[i]-x[i-1]);
	}
	i64 ans=x[n]-x[1];
	sort(pos.begin(),pos.end(),cmp64);
	m--;
	for(int i=n-2;i>=0&&m>0;i--){
		ans-=pos[i];
		m--;
	}
    cout<<ans<<endl;
}

【排序思想】Restricted Sorting

https://codeforces.com/contest/2188/problem/C

题目大意

QQ_1770031073994

思路

只要两个位置可以通过一些媒介交换,那么就绝对可以排序
首先,如果当前数已经在位置上了就不用动
其次,我们需要k最大
那么对于两个数\(a_i\)\(a_j\),选择序列中的最小和最大数作为交换媒介肯定会最大
(1)如果mx和mn只选一个,那么k为\(a_i\)\(a_j\)更靠近中转数的那一个
※(2)如果mx和mn都选,那么我可以只需要一个和mx调换,一个和mn调换,然后mx和mn互换来达成两个数的交换
QQ_1770031505591
因此,我在mx和mn距离中选取最大值,整个序列求最小值即可

\[\min_{\substack{a_i \neq b_i}} \left( \max\left( a_i - mn,\; mx - a_i \right) \right) \]

AC代码

const int N=3e5+10;
int n;
void solve(){
    cin>>n;
    vector<i64> a(n+1,0),b(n+1,0);
    for(int i=1;i<=n;i++){
        cin>>a[i];
        b[i]=a[i];
    }
    sort(b.begin(),b.end(),cmp<i64>);
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(a[i]==b[i]) cnt++;
    }
    if(cnt==n){
        cout<<-1<<endl;
        return;
    }
    i64 mx=-1,mn=1e9;
    for(int i=1;i<=n;i++){
        mx=whink_max<i64>(mx,a[i]);
        mn=whink_min<i64>(mn,a[i]);
    }
    i64 ans=1e9;
    for(int i=1;i<=n;i++){
        if(a[i]!=b[i]){
            i64 res=whink_max<i64>(mx-a[i],a[i]-mn);
            ans=whink_min<i64>(ans,res);
        }
    }
    cout<<ans<<endl;
}

【排序的条件】Reserved Reversals

https://codeforces.com/contest/2226/problem/D

题目大意

可以执行以下操作任意次:
(1)选择一个子串,子串最小值和最大值相加为奇数
(2)反转这个子串
求最终能否将数组变为非递减的

思路

(1)排序:只要【两个数之间能任意交换】,就能排序
->只要奇数与奇数之间 偶数和偶数之间能任意交换
(2)先考虑均为偶数的情况
对于每一个逆序对都需要交换
因为只能max+min为奇数的可以任意交换:奇数最大值比当前偶数最大值更大/奇数最小值比当前小的偶数更小

故排序流程如下:
QQ_1777435224128

代码

void solve(){
    cin>>n;
    vector<int> a(n+1,0);
    for(int i=1;i<=n;i++) cin>>a[i];
    vector<int> even,odd;
    int evenmx=-1,evenmn=1e9;
    int oddmx=-1,oddmn=1e9;
    for(int i=1;i<=n;i++){
        if(a[i]%2){
            oddmx=whink_max<int>(oddmx,a[i]);
            oddmn=whink_min<int>(oddmn,a[i]);
            odd.push_back(a[i]);
        }
        else{
            evenmx=whink_max<int>(evenmx,a[i]);
            evenmn=whink_min<int>(evenmn,a[i]);
            even.push_back(a[i]);
        }
    }
    bool is_ok=true;
    if(!even.empty()){
        int mx=-1;
        for(auto son:even){
            if(mx>son){
                if(mx>oddmx && son<oddmn){
                    is_ok=false;
                    break;
                }
            }
            else{
                mx=son;
            }
        }
    }
    if(!is_ok) NO;
    else{
        if(!odd.empty()){
            int mx=-1;
            for(auto son:odd){
                if(mx>son){
                    if(mx>evenmx && son<evenmn){
                        is_ok=false;
                        break;
                    }
                }
                else{
                    mx=son;
                }
            }
        }
        if(is_ok) YES;
        else NO;
    }
}
posted @ 2025-07-14 20:37  White_ink  阅读(10)  评论(0)    收藏  举报