链接:https://codeforces.com/contest/1262/problem/C
题意:给一个长度为n的括号序列,你需要通过最多n次翻转操作,使得能够得到恰好k个合法括号前缀。
因为有n次操作,所以可以得到任意的序列
只需要构造合法的k个即可;k个合法前缀,所以可以构造一种方案使得前(k-1)个是
()()()()....()这种形式,而最后的一个为剩下的括号((((...))))这样构造即可,如果当前位置i的括号符合构造后的括号,则不需任何操作;若不符合构造后的括号,则往后循环找到第一个位置j,j位置的括号为i位置需要的括号,并对[i,j]进行反转操作。所有的[i,j]即为答案。
代码:
#include<bits/stdc++.h> using namespace std; int n,k; string s; void solve_swap(int x,int y) { while(x<y) { swap(s[x],s[y]); x++,y--; } } string get_str(int n,int k)//构造字符串 { string tmp=""; for(int i=0; i<k-1; i++) { tmp+="("; tmp+=")"; } int len=n-tmp.size(); for(int i=0; i<len/2; i++) { tmp+="("; } for(int i=0; i<len/2; i++) { tmp+=")"; } return tmp; } void solve() { cin>>n>>k>>s; vector<pair <int ,int > > v; string str=get_str(n,k); for(int i=0; i<s.size(); i++) { if(s[i]!=str[i]) { for(int j=i+1; j<s.size(); j++) { if(s[j]==str[i]) { solve_swap(i,j); v.push_back(make_pair(i+1,j+1)); break; } } } } //cout<<s<<endl; cout<<v.size()<<endl; for(int i=0; i<v.size(); i++) printf("%d %d ",v[i].first,v[i].second); return ; } int main() { int t; cin>>t; while(t--) solve(); return 0;
}
还可以直接交换;
代码:
#include<bits/stdc++.h> using namespace std; int n,k; string s; string get_str(int n,int k)//构造字符串 { string tmp=""; for(int i=0; i<k-1; i++) { tmp+="("; tmp+=")"; } int len=n-tmp.size(); for(int i=0; i<len/2; i++) { tmp+="("; } for(int i=0; i<len/2; i++) { tmp+=")"; } return tmp; } vector<pair <int ,int > > v; void solve() { v.clear(); cin>>n>>k>>s; string str=get_str(n,k); for(int i=0; i<s.size(); i++) { if(s[i]!=str[i]) { for(int j=i+1; j<s.size(); j++) { if(s[j]==str[i]) { swap(s[i],s[j]); v.push_back(make_pair(i+1,j+1)); break; } } } } //cout<<s<<endl; cout<<v.size()<<endl; for(int i=0; i<v.size(); i++) printf("%d %d ",v[i].first,v[i].second); return ; } int main() { int t; cin>>t; while(t--) solve(); return 0;
}