zoukankan      html  css  js  c++  java
  • 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
    ",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;
    }
    
  • 相关阅读:
    JS加密对应的c#解码
    Content-Type: application/www-form-urlencoded
    使用abcpdf分页设置的问题
    Windows10远程报错:由于CredSSP加密Oracle修正
    ueditorUE 去掉本地保存成功的提示框!
    js进制转换
    缓存穿透 缓存雪崩 缓存击穿
    DTcms 模版用vs2015或2017 打开编辑时候 粘贴出问题 代码被调整
    通俗简述 依赖倒置•控制反转•依赖注入•面向接口编程 的思想
    tcp/ip
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12308825.html
Copyright © 2011-2022 走看看