AtCoder arc147. B Swap to Sort 题解

题目描述

https://atcoder.jp/contests/arc147/tasks/arc147_b

输入样例
4
3 2 4 1
输出样例
4
A 3
B 1
B 2
B 2

算法

(贪心) O ( n 2 ) O(n^2) O(n2)

首先我们定义状态,将 $a[i] % 2 != i % 2 $叫做一个坏状态,否则为一个好状态,坏状态花费为 1 1 1,好状态花费为 0 0 0

总花费记为 c n t cnt cnt

A A A 操作会改变下标为 i i i i + 1 i + 1 i+1 的状态

如果 i i i 是一个好状态, i + 1 i + 1 i+1 是一个坏状态,那么经过 A A A 操作之后, i i i 为一个坏状态, i + 1 i + 1 i+1 为一个好状态

那么 c n t cnt cnt 的值不会改变

同理可得,如果 i i i i + 1 i + 1 i+1 都是好状态,经过 A A A 操作之后 c n t + = 2 cnt += 2 cnt+=2

如果 i i i i + 1 i + 1 i+1 都是坏状态,那么经过 A A A 操作之后 c n t − = 2 cnt -= 2 cnt=2

B B B 操作不会改变 c n t cnt cnt 的值

那么在这里可以知道,如果初始坏状态的数量为 k k k,那么对于 操作 A A A 执行的次数一定 ≥ \geq 1 2 k \frac{1}{2}k 21k

接下来,怎么样要 A A A 的操作次数 = 1 2 k =\frac{1}{2}k =21k

那样,我们每次的操作必定要改变状态,而且必须要让坏状态变好

如何做到这一点呢?

方法就是利用 B B B 操作先将坏状态全部放入数组的开头或者结尾,也就是将

XOXOXOXO

变成

OOOOXXXX

经过 A A A 操作之后, c n t = 0 cnt = 0 cnt=0,那么再次进行 B B B 操作进行排序就可以啦

C++ 代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<unordered_map>
#include<vector>
#include<queue>

using namespace std;


const int N=410;

int a[N];
vector<string> v;
vector<pair<char,int>> ans;

int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++) 
		for(int j=1;j<=n-2;j++) 
			if(a[j]%2!=a[j+2]%2 && a[j]%2!=j%2) 
			{
		string t="B "+to_string(j);
		v.push_back(t);
		ans.push_back({'B',j});
		swap(a[j],a[j+2]);
			}
	//首先通过B把bad全部往后挪
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j+2<=n;j++)
		{
			if(a[j]%2!=a[j+2]%2)//一个好一个坏
			{
				if(a[j]%2!=j%2)//j是坏的
				{
					string t="B "+to_string(j);
					v.push_back(t);
					ans.push_back({'B',j});
					swap(a[j],a[j+2]);
				}
			}
		}
	}
//	for(int i=1;i<=n;i++) cout<<a[i]<<" ";
//	cout<<endl;
	for(int i=1;i+1<=n;i++)
	{
		if(a[i]%2!=i%2)
		{
			if(a[i+1]%2!=a[i]%2)
			{
				string t="A "+to_string(i);
				v.push_back(t);
				ans.push_back({'A',i});
				swap(a[i],a[i+1]);
			}
		}
	}
//	for(int i=1;i<=n;i++) cout<<a[i]<<" ";
//	cout<<endl;

	for(int i=1;i<=n;i++)
	{
		for(int j=1;j+2<=n;j++)
		{
			if(a[j]>a[j+2])
			{
				string t="B "+to_string(j);
				v.push_back(t);
				swap(a[j],a[j+2]);
				ans.push_back({'B',j});
			}
		}
	}
	cout<<ans.size()<<endl;
	for(auto x:ans) cout << x.first << ' ' << x.second << endl;
//	cout<<v.size()<<endl;
//	for(auto t:v) cout<<t<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值