• 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明)J. Parallel Sort(思维/构造)


    链接:https://ac.nowcoder.com/acm/contest/12548/J
    来源:牛客网

    题目描述

    As a master of parallel computing, schwer is recently considering about the method to achieve quick sorting on parallel computers. He needs your help!

    Given a permutation (p1,⋯ ,pn)(p1,⋯,pn), you need to sort the permutation with minimum number of rounds. In a single round, one can take many pairs of integers (x1,y1),⋯ ,(xk,yk)(x1,y1),⋯,(xk,yk) as long as the values of x1,y1,⋯ ,xk,ykx1,y1,⋯,xk,yk are pairwise distinct. Then with the help of kk CPUs, for each i∈[1,k]i∈[1,k], the value of pxipxi and pyipyi will be switched immediately. Note that a permutation (p1,⋯ ,pn)(p1,⋯,pn) is sorted if for every integer i∈[1,n]i∈[1,n], pi=ipi=i holds.

    Take some examples. Assume that n=4n=4. For p=(1,2,3,4)p=(1,2,3,4), the minimum number of round is 00 as it is already sorted. For p=(4,3,2,1)p=(4,3,2,1), the answer is 11, as you can swap the indices (1,4)(1,4) and (2,3)(2,3) simultaneously.

    输入描述:

    he first line of input contains a single integer n(1≤n≤105)n(1≤n≤105), indicating the length of the permutation.The second line contains nn integers p1,...,pn(1≤pi≤n)p1,...,pn(1≤pi≤n), the given permutation. It is guaranteed that these integers form a permutation, that is, for every integer i∈[1,n]i∈[1,n] there exists an unique integer j∈[1,n]j∈[1,n] such that pj=ipj=i.
    

    输出描述:

    The first line of output should contain a single integer mm, the minimum number of rounds to get the permutation sorted. Then print mm line to show one possible solution.The ii-th of the next mm lines should describe the ii-th round of your solution, beginning with a single integer kk, and followed by 2k2k integers x1,y1;⋯ ;xk,ykx1,y1;⋯;xk,yk. The constraints that 1≤xi,yi≤n1≤xi,yi≤n and the 2k2k integers are pairwise distinct must be held.
    

    示例1

    输入

    复制

    4
    1 2 3 4
    

    输出

    复制

    0
    

    示例2

    输入

    复制

    4
    4 3 2 1
    

    输出

    复制

    1
    2 1 4 2 3
    

    这个题和之前蓝桥杯交换瓶子那个题有点像https://www.cnblogs.com/lipoicyclic/p/13959642.html,不过还是看了题解才会的TAT。对于全排列操作使之有序,如果限制交换位置相邻的话方法是逆序对,如果不限制相邻就是找环了。首先易知对于两个点的小环可以第一轮就换过来,这样不会影响后续操作,对于大环比如2 3 4 5 1或者 3 4 1 2,第一轮则要把它拆成多个两个点的小环,然后第二轮换过来。特别注意拆环的时候,如果是偶环直接对称交换,比如3 4 1 2拆完后得到2 1 4 3,如果是奇环也是对称交换,比如2 3 4 5 1得到1 5 4 3 2,这样一定能保证奇数个点归位,剩下的是两个点的小环。

    #include <iostream>
    #include <vector>
    using namespace std;
    int n, p[100005], id[100005];
    bool vis[100005] = { 0 };
    bool ok() {
    	for(int i = 1; i <= n; i++) {
    		if(p[i] != i) return false;
    	}
    	return true;
    }
    int main() {
    	cin >> n;
    	for(int i = 1; i <= n; i++) {
    		cin >> p[i];
    		id[p[i]] = i;
    	}
    	if(ok()) {
    		cout << 0;
    		return 0;
    	}
    	vector<pair<int, int> > round1;
    	vector<pair<int, int> > round2;
    	vector<vector<int> > v;
    	for(int i = 1; i <= n; i++) {
    		if(vis[i]) continue;
    		if(p[i] == i) {
    			vis[i] = 1;
    			continue;
    		}
    		int j = p[i];
    		if(i == p[j]) {
    			round1.push_back(make_pair(i, j));
    			vis[i] = vis[j] = 1;
    			swap(p[i], p[j]);
    			id[i] = i, id[j] = j;
    		} else {
    			int x = p[i];
    			vis[i] = 1;
    			vector<int> tmp;
    			tmp.push_back(x);
    			while(x != i) {
    				vis[x] = 1;
    				x = p[x];
    				tmp.push_back(x);
    			}
    			v.push_back(tmp);
    		}
    	}
    	if(ok()) {
    		cout << 1 << endl;
    		cout << round1.size() << " ";
    		for(int i = 0; i < round1.size(); i++) {
    			cout << round1[i].first << ' ' << round1[i].second << ' ';
    		}
    		return 0;
    	}
    	for(int i = 0; i < v.size(); i++) {//还在round1
    		//此时奇环处理完后变成偶环了
    		for(int j = 0; j < v[i].size() / 2; j++) {
    			round1.push_back(make_pair(id[v[i][j]], id[v[i][v[i].size() - 1 - j]]));
    			swap(p[id[v[i][j]]], p[id[v[i][v[i].size() - 1 - j]]]);
    			swap(id[v[i][j]], id[v[i][v[i].size() - 1 - j]]);
    		}
    	}
    	for(int k = 1; k <= n; k++) id[p[k]] = k;
    	//round2
    	for(int i = 1; i <= n; i++) {
    		if(p[i] == i) {
    			continue;
    		}
    		round2.push_back(make_pair(i, p[i]));
    		swap(p[i], p[p[i]]);
    	}	
    	cout << 2 << endl;
    	cout << round1.size() << " ";
    	for(int i = 0; i < round1.size(); i++) {
    		cout << round1[i].first << ' ' << round1[i].second << ' ';
    	}
    	cout << endl;
    	cout << round2.size() << " ";
    	for(int i = 0; i < round2.size(); i++) {
    		cout << round2[i].first << ' ' << round2[i].second << ' ';
    	}
    	return 0;
    }
    
  • 相关阅读:
    游戏修改器编写原理
    欲练 CSS ,必先宫 IE
    HTML结构化:CSS布局入门指南
    用css来定义table的样式
    HTML表格无空隙嵌套方法
    CSS布局学习笔记
    绽放最后的一丝美丽
    这种感觉真爽
    诗人,是否还有生存的空间
    提升人气的秘密武器
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14621227.html
Copyright © 2020-2023  润新知