Problem: A题 Almost Correct
题意
思路
我们可以考虑给定字符串与其他字符串的不同之处,首先可以发现当前字符串与其他字符串肯定是存在某些地方不同,但这样的不同没有共性,我们想能不能把它给固定,使得给定字符串与其他字符串都有相同的不同之处。
首先我们考虑固定一个值,就是在一些操作后只有给定字符串的第一位为,其他字符串第一位都是,发现必然不能实现,因为想保持某一位为,就只能让这一位对其前面数和后面的为的位置操作,但必然有与给定字符串不同的字符串但是后面的位置相同。
再考虑固定两个值,我们可以固定一个最左边的(设该下标为),和最右边的(设该下标为)。操作方式就是这个与其他的交换,与其他的进行交换。为什么可以因为对于和给定字符串位置相同位置相同只能是给定字符串本身,其他的字符串一定有不同的地方,这个不同的地方就会导致这两个位置的与给定字符串不同。至此,我们发现了一个使给定字符串特殊于所有其他字符串的地方。
我们找到了不同,然后可以对除了和以外所位置进行排序,排完序后因为位置为,位置为(因为给定字符串本身保证未排序,所以),给定字符串一定是未成功排序的。同时,其他字符串这两个位置一定最少有一个是被成功排序的。我们取为给定字符串中0的个数(),发现给定字符串的分界线一定再和之间,而其他的未排序成功的字符串分界线一定向左向右有所偏移。因此,只要将和内交换,r和交换即可。
解题方法
按照思路中来:
- 将最左边和所有来一遍交换,最右边和所有交换。
- 将除了以外位置排序,因为操作的性质,导致所有一定是向后移动,向前。所以只要对每个位置和后面所有位置实施交换即可。
- 将和内交换,注意先和最远处交换,即先和,再,先,再和交换同理。
复杂度
- 时间复杂度:
每次操作是 ,最多为,大概是。
- 空间复杂度:
开了个数组存每次操作,是
Code
#include <bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
#define endl "\n"
#define ll long long
#define pii pair<int, int>
void solve()
{
int n;
string s;
cin >> n >> s;
//操作1
vector<int> S0, S1;
for(int i = 0; i < n; i++){
if(s[i] == '0') S0.emplace_back(i + 1);
else S1.emplace_back(i + 1);
}
int l = S1.front(), r = S0.back(), l0 = S0.size(), l1 = S1.size();
vector<pii> res;
for(int i = 1; i < l1; i++) res.emplace_back(make_pair(l, S1[i]));
for(int i = 0; i < l0 - 1; i++) res.emplace_back(make_pair(S0[i], r));
//操作2
for(int i = 1; i <= n; i++){
if(i == l || i == r) continue;
for(int j = i + 1; j <= n; j++){
if(j == l || j == r) continue;
res.emplace_back(make_pair(i, j));
}
}
//操作3
for(int i = 1; i < l; i++) res.emplace_back(make_pair(i, l));
for(int i = l0; i > l; i--) res.emplace_back(make_pair(l, i));
for(int i = l0 + 1; i < r; i++) res.emplace_back(make_pair(i, r));
for(int i = n; i > r; i--) res.emplace_back(make_pair(r, i));
//输出
cout << res.size() << endl;
for(auto [x, y] : res) cout << x << ' ' << y << endl;
}
int main()
{
cout.tie(nullptr);
cin.tie(nullptr);
ios::sync_with_stdio(false);
int _ = 1;
cin >> _;
while (_--)
solve();
return 0;
}