• Codeforces 1148C(思维)


    题面

    给出一个长度为n的排列a,每次可以交换序列的第i个和第j个元素,当且仅当(2 imes |i-j| geq n),求一种交换方案,让序列从小到大排好序

    分析

    重点是考虑我们怎么把第x个数换到第i个位置上,且尽量不破坏其他数的位置

    我们用序列的第1,n个数作为跳板,如果与n的距离满足条件就与n交换,否则与1交换,定义find(x)为x应该和谁交换。

    1.把x与find(x)交换,此时x到了find(x)

    2.find(x)与find(i)交换,此时x到了find(i)

    3.find(i)与i交换,此时x到了i

    我们可以发现这样交换只会对1,n的数产生交换,其他无关数的位置不变。我们只要对2~n-1的数执行上述操作,最后我们再看看a[1]是不是1,然后判断需不需要交换(1,n)即可

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm> 
    #include<vector> 
    #define maxn 300005
    using namespace std;
    
    int n; 
    vector< pair<int,int> >ans;
    int a[maxn];
    int pos[maxn];//值为i的数的位置 
    inline int find(int x){
    	if(2*(n-x)>=n) return n;
    	else return 1;
    } 
    void change(int x,int y){
    	ans.push_back(make_pair(x,y));
    	swap(pos[a[x]],pos[a[y]]);
    	swap(a[x],a[y]);
    } 
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		pos[a[i]]=i;
    	}
    	for(int i=2;i<n;i++){
    		int t=pos[i];
    		change(t,find(t));
    		if(find(t)!=find(i)) change(find(t),find(i));
    		change(i,find(i)); 
    	}
    	if(a[1]!=1) change(1,n);
    	printf("%d
    ",ans.size());
    	for(auto p : ans){
    		printf("%d %d
    ",p.first,p.second); 
    	} 
    }
    
    
  • 相关阅读:
    php高级进阶系列文章--第二篇(PHP基础知识复习)
    开发常用linux命令
    composer 包管理工具学习总结
    微信菜单加emoji图标
    onethink导出excel
    onethinkp导入excel
    导航效果css
    php发送邮件
    js初学者的div移动
    html图片预览
  • 原文地址:https://www.cnblogs.com/birchtree/p/10962041.html
Copyright © 2020-2023  润新知