比赛记录:Educational Codeforces Round 149 (Rated for Div. 2) A~D

传送门:CF

前提提要:这场狠狠的掉分.C题刚开始少了一个特判,导致自己对自己的构造方法产生了疑问,然后就一直在做无用思考,后来交的时候排名就贼后面,然后D题的题面简直稀烂(虽然D题看懂之后极其简单…),赛时根本看不懂D题意,最终rating掉完.不亏是教育场,被狠狠的教育了

A题:A. Grasshopper on a Line

赛时随便口胡了一贪心想法,然后就过了.写题解时简单思考了一下,发现当时的贪心想法只是碰巧过了而已…
对于x%k!=0的情况,直接就可以跳x.
对于x%k=0的情况,显然x可以先跳x-1,然后再跳1,因为k>1
代码的话附赛时口胡代码,正解就懒得再写了,反正口胡的也过了(bushi

#include 
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3fc
int main() {
	int T=read();
	while(T--) {
		int x=read(),k=read();
		vector<int>ans;
		int temp=0;
		while(x) {
			int r=x;
			while(r%k==0) r--;
			ans.push_back(r);
			x-=r;
			temp++;
		}
		cout<<temp<<endl;
		for(int i=0;i<ans.size();i++) {
			cout<<ans[i]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

B题:B. Comparison String

简单思维题.不难发现最终的答案就是最长的相同连续字符+1.证明显然,随便手画一下就能搞清楚了,此处就不在赘述了

#include 
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
int main() {
	int T=read();
	while(T--) {
		int n=read();
		string s;
		cin>>s;int maxx=-int_INF;int cnt=1;
		for(int i=1;i<s.length();i++) {
			if(s[i]==s[i-1]) {
				cnt++;
			}
			else {
				maxx=max(maxx,cnt);
				cnt=1;
			}
		}
		maxx=max(maxx,cnt);
		cout<<maxx+1<<endl;
	}
	return 0;
}

C题:C. Best Binary String

首先先讲讲需要特判的一些情况.注意全部都是 ? ? ?或者 1 1 1,或者 0 0 0,或者没有 ? ? ?的情况.
然后我们贪心的去想想这道题.首先当我们的?在开头时,此时我们可以直接填0,然后?在结尾时,我们直接填1,此时这么填显然是最优的,因为我们可以不用考虑这些数字了.

对于?在中间的情况,我们分析连续的?区间的前后是什么(显然对于一个连续的?区间,我们应该将其赋值为同一个值是最优的).当我们前后数字一样时,我们就应该填那一个数字,假设我们的前后数字不同时,此时我们填0或1都行.

对于前后数字一样时,我们此时显然应该填那一个数字.不然的话我们就需要用一个花费来将前面的数字换到后面去或者后面的数字换到前面来.此时就不优了.
对于前后数字不同时,无论我们填那一个数字对于最后的花费都是没有影响的,这个可以简单那枚举一下情况,此处就不在赘述了.

#include 
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
int main() {
	int T=read();
	while(T--) {
		string s;cin>>s;
		if(s.find('?')==s.npos) {
			cout<<s<<endl;
			continue;
		}
		if(s.find('1')==s.npos&&s.find('0')==s.npos) {
			for(int i=0;i<s.length();i++) {
				cout<<0;
			}
			cout<<endl;
			continue;
		}
		string ans="";int l=0;
		if(s[0]=='?') {
			while(s[l]=='?') {
				l++;
			}
		}
		for(int i=0;i<l;i++) ans+=s[l];
		int r=s.length()-1;
		if(s.back()=='?') {
			while(s[r]=='?') {
				r--;
			}
		}
		for(int i=l;i<=r;i++) {
			if(s[i]=='?') {
				int pos1=i-1;
				while(i+1<=r&&s[i+1]=='?') {
					i++;
				}
				int pos2=i+1;
				if(s[pos1]!=s[pos2]) {
					for(int j=pos1+1;j<=pos2-1;j++) {
						ans+='0';
					}
				}
				else {
					for(int j=pos1+1;j<=pos2-1;j++) {
						ans+=s[pos2];
					}
				}
			}
			else {
				ans+=s[i];
			}
		}
		for(int i=r+1;i<s.length();i++) {
			ans+=s[r];
		}
		cout<<ans<<endl;
	}
	return 0;
}

D题:D. Bracket Coloring

题意依托答辩.需要十分仔细的研读(很难不让人以为是中国人出的题).
看完题意之后思路就很清晰了.显然我们最终的答案最多也就是分成两个子序列.为什么呢.
我们可以将所有的合法子序列情况分为一下几种:
比赛记录:Educational Codeforces Round 149 (Rated for Div. 2) A~D_第1张图片

然后我们发现1,2两种情况是可以合并成同一个子序列的(当然3,4也是).并且我们发现对于所有的可满足括号序列,我们总可以拆分成上述几种子序列(这个手画一下就挺清楚明白的,证明就不证了,偷懒一下,逃).
所以我们在跑字符串的时候只要看看当前的括号属于哪一种情况即可.这个需要分类讨论:
对于 ′ ′ ( ′ ′ ''('' ′′(′′的情况,假设我们之前有没有配对的 ′ ′ ) ′ ′ '')'' ′′)′′,那么当前就是第三,四种情况;假设我们没有 ′ ′ ) ′ ′ '')'' ′′)′′,那么此时我们就属于第二种或第一种情况;
对于 ′ ′ ) ′ ′ '')'' ′′)′′的情况,类似分析即可.

#include 
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
int main() {
	int T=read();
	while(T--) {
		int n=read();
		string s;cin>>s;map<int,int>mp;
		vector<int>ans;int cnt1=0,cnt2=0;//cnt1代表(,cnt2代表)
		for(int i=0;i<s.length();i++) {
			if(s[i]=='(') {
				if(cnt2==0) {
					cnt1++;
					ans.push_back(2);
					mp[2]++;
				}
				else {
					cnt2--;
					ans.push_back(1);
					mp[1]++;
				}
			}
			else {
				if(cnt1==0) {
					cnt2++;
					ans.push_back(1);
					mp[1]++;
				}
				else {
					cnt1--;
					ans.push_back(2);
					mp[2]++;
				}
			}
		}
		if(cnt1||cnt2) {
			cout<<"-1"<<endl;
			continue;
		}
		int Size=(mp[1]?1:0)+(mp[2]?1:0);
		cout<<Size<<endl;
		if(Size==1) {
			for(int i=0;i<ans.size();i++) {
				cout<<1<<" ";
			}
		}
		else {
			for(int i=0;i<ans.size();i++) {
				cout<<ans[i]<<" ";
			}
		}
		cout<<endl;
	}
	return 0;
}

你可能感兴趣的:(c++算法,#,各类比赛,算法,c++)