Educational Codeforces Round 147 (Rated for Div. 2) (A-C)

A. Matching

大致题意:给你一个由数字和“ ?”组成的字符串,“ ?”可以替换成任意一位数(0-9),问这个字符串可以匹配多少个数字,所匹配的数字不能有前置0.

思路:从头遍历字符串,如果第一位为0,则直接输出0;其他情况遇到 “ ?”判断其位置,因为所匹配的数字不能有前置0,所有如果 ‘ ?’在第一位上则结果乘以9,其他位置则结果乘以10。(注意所匹配的字符串不一定要变化而来,给定的字符串如果没有 “ ?”且第一位不为0,则结果为 1,这唯一的结果就是它自己  )。

ac代码:

#include<iostream>
#include<algorithm>
#include<cstring >

using namespace std;
#define ll long long 

const  int N=2e5+10;

void solve(){
	
	string s;
	cin>>s;
	int ans=1;
	if(s[0]=='0')
	{
		cout<<0<<endl;
		return ;
	}
	for(int i=0;i<s.size();i++){
		if(s[i]=='?'&&i==0) //?在第一位 
			ans*=9;
		else if(s[i]=='?') // ? 不在第一位 
			ans*=10;
	}
	cout<<ans<<endl; 
}

int main(){
	int t;
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

B. Sort the Subarray

题意:给定两个数组a,b(a,b不相等);求一个最大区间 [ L,R ],将 数组a这个区间的数从小到大排序,使得a==b。

思路:我们可以通过找b数组中的最大上升子序列(这个最大上升子序列要存在一个位置的元素和a数组不同)即可。

ac代码:

#include<iostream>
#include<algorithm>
#include<cstring >
#include<queue>

using namespace std;
#define ll long long 

const  int N=2e5+10;

int a[N],b[N];

void solve(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		cin>>b[i];
	}
	int len=0;
	int l=0,r=0;
	for(int i=1;i<=n;i++){
		bool ok=false;
		int cnt=0;
		int j=i;
		while(b[i]<=b[i+1]&&i<n){
			if(a[i]!=b[i]) ok=true;
			cnt++;
			i++;
		}
		if(cnt>len&&ok){
			len=cnt;
			l=j;
			r=i;
		}
	}
	cout<<l<<" "<<r<<endl;
}

int main(){
	int t;
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

 C. Tear It Apart

大致题意:

        给定一个字符串s,由小写拉丁字母组成。在一次操作中,可以在其中选择几个(一个或多个)位置,所选位置不能彼此相邻。然后从字符串中删除选定位置上的字母。结果部分被连接起来,而不改变它们的顺序。要使得到的 s 中的所有字母一样,最少需要多少次操作。

思路:

        我们对于每个字母都进行贪心处理删除,最后再所有字符操作中选择最小的操作数。那怎么进行贪心处理呢?我们要保留的字符会将给定的字符串换成多个部分,对于每个部分,我们都进行一个隔一个的删除处理,则单个部分的处理的次数为它的长度取log2。

        举个例子:codeforces  我们选字符o保留 那么它将字符分成 c   def    rces三个部分,由于各部分是保留字符分隔的所有,每个部分的删除是不会相连影响的。则将o保留的操作数为 rces的长度 4 取 log2.

        为什么是 取log2呢?因为我们每部分都一个隔一个的删除,相当于长度每次都除以2,那么删除次数就是长度取 log2.    

        

ac代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<set>

using namespace std;
#define ll long long 

const  int N=2e5+10;

int a[N],b[N];
set<char> st;

int cc[200]; //存删除对应字符的最大长度

void solve(){
	st.clear();
	string s;
	cin>>s;
	memset(cc,0x3f,sizeof cc);
	for(int i=0;i<s.size();i++){
		st.insert(s[i]);
	}
	for(auto c:st){
		int mx=0;
		int len=0;
		for(int i=0;i<s.size();i++){
			if(s[i]==c){
				mx=max(mx,len);
				len=0;
			}
			else
				len++;
		}
		if(len) mx=max(len,mx);
		cc[c]=mx;
	}
	int mi=1e9;
	for(int i='a';i<='z';i++){
		mi=min(mi,cc[i]); //再所有最大里面 选一个最小的
	}
	int ans=0;
	while(mi){
		mi/=2;
		ans++;
	}
	cout<<ans<<endl;
}

int main(){
	int t;
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值