div2 #602 C(构造括号问题)

题目链接
先给你一串长为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;
}
发布了51 篇原创文章 · 获赞 6 · 访问量 1660

猜你喜欢

转载自blog.csdn.net/qq_43555854/article/details/103378262