题目链接:https://codeforces.com/problemset/problem/1864/B
题目大意:对一串字符串只能进行以下两种操作:1.swap(str[i],str[i+2]),1<=i<=n;2.选择一个i,将区间[i,i+k-1]进行翻转。要求求出该字符串最小字典序的形式。
解题思路:第一个操作代表我们可以随意交换下标同为奇数或者偶数的字符,对下标为偶数和奇数的字符串分别进行排序。第二个操作需要对k为偶数还是奇数进行分别讨论:当k为偶数时,区间进行翻转时,下标的奇偶性不会发生变化,所以字典序最小的就是将下标为奇数和偶数的分别排序后合并;当k为奇数时,选择一个i进行[i,i+k-1],[i+1,i+k]两次翻转操作,可以发现有字符的下标的奇偶性发生了变化,因此字典序最小就是相当于对整个字符串进行排序。
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 10;
char ch[maxn], a[maxn], b[maxn];
int main()
{
int t;
cin >> t;
while (t--)
{
int n, k, cnt = 0, cnt1 = 0;
cin >> n >> k;
for (int i = 0; i < n; i++)
{
cin >> ch[i];
if ((i + 1) % 2)a[cnt++] = ch[i];
else b[cnt1++] = ch[i];
}
if (k % 2 == 0)
{
sort(ch, ch + n);
}
else
{
sort(a, a + (n % 2 ? n / 2 + 1 : n / 2));
sort(b, b + n / 2);
cnt = 0, cnt1 = 0;
for (int i = 0; i < n; i++)
{
if ((i + 1) % 2)
{
ch[i] = a[cnt++];
}
else
{
ch[i] = b[cnt1++];
}
}
}
for (int i = 0; i < n; i++)
{
cout << ch[i];
}
cout << endl;
}
}