E.小沙的印章

E.小沙的印章

题目描述

小沙在玩团队游戏,他的团队需要赢得比赛,小沙的团队包括小沙在内有 n 个人,每个人有一种与其他人不同的印章。他们围成一个环,分别编号为 1 , 2 , 3 ... n,一开始 x 与 x−1 和 x+1 相邻,特别的 1 与 n 相邻。在每轮游戏中,每个人可以和他相邻的其中一个人组成搭档,也可以不组。然后每对搭档交换位置。

除了交换位置的时候,在任何时候,每个人都可以给他相邻的人印上他的印章图案的印花,每个人的印章只能自己使用,不得传递。

你需要提出一种方案使得 n 轮内每个人收集全所有印花。每个人默认拥有自己印章的印花

输入描述:

输入一个整数 n ,\(1\le n \le 10^3\)

输出描述:

第一行输出一个整数 k ,代表总共交换的多少轮。

随后输出 k 轮,其中 \(0 \le k \le n\)

每轮第一个行一个整数 q 代表本轮交换多少对。

随后的 q 行,每行输出两个整数代表交换者的编号。

输入

4

输出

1
1
3 4

说明

一开始每个人能获得到的印花分别为:
1:1 2 4
2:1 2 3
3:2 3 4
4:1 3 4

当交换之后
1获得3
2获得4
3获得1
4获得2
所有人均获得所有印花。

思路点拨

  • 难点在于构造。

  • 题目没有要求最少或者最多,只要找到一种能达到要求的即可,思考冒泡排序的过程,针对一开始递增序列变为最后递减序列,整个过程的冒泡排序正好可以使得任何两项都会相遇。

  • 有一个注意点,只能移动一对,也就是说冒泡排序,这一对交换了,必须让i += 2,不能用i+1去冒泡排序,i 和 i + 1已经交换过了,不能拿交换过的i + 1在和 i +2交换,不符合一对原则,不可以再去交换。

  • 利用函数std::is_sorted(a.begin(),a.end(),std::greater()),判断是否为递减序列,没有greater 作用是判断是否为递增序列。

提交代码

// Problem: 小沙の印章
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/46813/E
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using i64 = long long;

int main() 
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	
	int n;
	std::cin >> n;
	
	std::vector<int> a(n);
	std::iota(a.begin(), a.end(),1);
	
	std::vector< std::vector<std::pair<int,int> > > ans;
	while(!std::is_sorted(a.begin(),a.end(),std::greater<int>()))
	{
		std::vector<std::pair<int,int> > s;
		for(int i = 1; i < n; i++)
		{
			if(a[i] > a[i - 1])
			{
				std::swap(a[i], a[i - 1]);
				s.emplace_back(a[i], a[i - 1]);
				i++;
			}
		}
		ans.push_back(s);
	}
	std::cout << ans.size() << "\n";
	for(auto v : ans)
	{
		std::cout << v.size() << "\n";
		for(auto item : v)
		{
			std::cout << item.first << " " << item.second << "\n";
		}
	}
    
    return 0;
}

posted @ 2023-02-24 22:42  哲远甄骏  阅读(31)  评论(0)    收藏  举报