Codeforces 1262C Messy

刚读完题一点思路没有,研究了一个多小时都没研究出来,之后听别人说暴力,我吐血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\n",v.size());
		for(auto e:v) printf("%d %d\n",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;
}
posted @ 2019-11-25 14:36  YuhanのBlog  阅读(82)  评论(0编辑  收藏  举报