刚读完题一点思路没有,研究了一个多小时都没研究出来,之后听别人说暴力,我吐血orz,又狠狠掉了一波分QAQ;
思路:
1.第一种想法就是暴力置换了,置换到合适的为止,但是本菜鸡就是不想暴力QAQ;
2.第二种想法就是研究它变化的规律,过程并不严谨,甚至有些玄学,大家可以自己推一推,这里直接说结论:
1)首先将给的序列变换成合法的序列,同时记录它一个有几个合法前缀序列cnt
;
2)一个序列有k
个合法前缀序列其实意思就是这个序列由k
个不可再分的合法序列组成;
3)如果cnt<k
,说明我们需要构造出更多的合法序列,我们从前往后遍历每一个长度大于2
的合法序列,则这个序列必定可以分为()
和剩下的部分,分的方法就是选取这个序列第二个位置和第一个)
的位置(闭区间),然后逆序这个区间就ok了,然后每置换一次,合法的序列数就会加一,一直到k
就ok了;
例如()(())
,第一个()
不可再分,第二个((()))
,选取位置2、4
,换完就是()(())
;
4)如果cnt>k
,说明我们需要减少合法序列的个数,那么就要合并,合并就简单啦,找两个相邻的合法序列,前一个序列末尾的)
和后一个序列的首个(
置换就ok了~;
例如(()())(())()
是我们找出第一个序列(()())
和第二个(())
,将第一个序列的末尾元素和第二个序列的首个元素置换,第三个序列不变,就会得到(()()()())()
,这样就合并完成了~
3.上面的方法还是太蠢笨了,最简洁的思路就是我们自己构造一个合适的,然后依次循环,比较自己构造的和原序列每个位置是否一致,如果不一致,就在原序列中继续往下找,找到一样的swap
一下就好了,这个变化是符合逆序规则的(至于原因自己动手模拟一下就ok了);
方法二代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
#define fi first
#define sc second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define rp(i,n) for(int i=0;i<n;i++)
const int MAX_N=2005;
int a[MAX_N];
vector<P> v;
void make_less(int& k,int& cnt){
int ans=a[0],pos=1;
while(cnt>k){
while(ans) ans+=a[pos++];
if(ans==0){
v.pb(mp(pos,pos+1));
swap(a[pos-1],a[pos]);
cnt--;ans=2;
}
}
}
void make_more(int& k,int& cnt){
int p1=0,p2=1;
while(cnt<k){
while(a[p1]==1&&a[p2]==-1){p1+=2;p2+=2;}
while(~a[p2]) p2++;
v.pb(mp(p1+2,p2+1));
reverse(a+p1+1,a+p2+1);
cnt++;p1+=2;p2=p1+1;
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,k;
scanf("%d%d",&n,&k);
int ans=0,pos=-1,cnt=0;
v.clear();
rp(i,n){
char c;
do{c=getchar();}while(c!='('&&c!=')');
a[i]=(c=='('?1:-1);
ans+=a[i];
if(ans<0&&pos==-1) pos=i;
if(ans==0){
cnt++;
if(~pos){
v.pb(mp(pos+1,i+1));
reverse(a+pos,a+i+1);
pos=-1;
}
}
}
if(cnt<k) make_more(k,cnt);
else if(cnt>k) make_less(k,cnt);
printf("%d
",v.size());
for(auto e:v) printf("%d %d
",e.fi,e.sc);
}
return 0;
}
方法三代码(思路简洁):
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
#define fi first
#define sc second
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
vector<P> v;
int main(){
IOS;
int t;
cin>>t;
while(t--){
v.clear();
int n,k;
cin>>n>>k;
string s,str="";
cin>>s;
for(int i=0;i<k-1;i++) str+="()";
int num=(n-((k-1)<<1))>>1;
for(int i=0;i<num;i++) str+="(";
for(int i=0;i<num;i++) str+=")";
for(int i=0;i<str.length();i++){
if(s[i]!=str[i]){
int pos=i+1;
while(s[pos]!=str[i]) pos++;
v.pb(mp(i+1,pos+1));
swap(s[i],s[pos]);
}
}
cout<<v.size()<<endl;
for(auto x:v) cout<<x.fi<<' '<<x.sc<<endl;
}
return 0;
}