题目描述
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;
}