题目链接
先给你一串长为n的字符串,然后你做不超过n次颠倒某段区间的操作,使之生成一个有k个合法前缀括号的字符串。(题目保证可以构造出解)
思路 :
先构造出合法的字符串 (k - 1)个单独的(), 剩下多余的括号就单独分给最后一个大括号(((()))),这样就能正好有k个前缀。
然后就从1~n遍历 ,每次都让第i个位置的字符一样, 这样就正好做了n次。符合要求,输出即可。
ac代码:
#include <bits/stdc++.h>
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, n) for (int i = (int)(n) - 1; i >= 0; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)
using namespace std;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpi;
typedef vector<vi> vvi;
typedef long long i64;
typedef vector<i64> vi64;
typedef vector<vi64> vvi64;
typedef pair<i64, i64> pi64;
typedef double ld;
template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }
int t, k, n;
string s;
void fk(string &s, int l, int r) {
while (l < r) {
swap(s[l], s[r]);
++l;
--r;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.precision(10);
cout << fixed;
#ifdef LOCAL_DEFINE
freopen("in", "r", stdin);
#endif
cin >> t;
while (t--) {
string t;
cin >> n >> k;
cin >> s;
int ak = k - 1;
forn(i, ak) {
t += "()";
}
forn(i, (n - 2 * ak) / 2) {
t += "(";
}
forn(i, (n - 2 * ak) / 2) {
t += ")";
}
cout << n << '\n';
forn(i, n) {
int now = i;
while (s[now] != t[i]) ++now;
cout << i + 1 << " " << now + 1 << '\n';
fk(s, i, now);
}
}
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}