CF Educational Codeforces Round 147(A~D)

CF1821A Matching

题意:给一个带问号的数,问有多少个数可以和它相匹配。

思路:统计有多少个问号,每一个问号,答案*10,特判一下最高位为问号则/10*9,另外还需要特判一下前置零的情况。

#include<bits/stdc++.h>
using namespace std;
int t,ans,pos;//sum表示问号的个数,pos表示问号在不在最高位 
char s[10];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>s;
		pos=0; ans=1;
		int n=strlen(s);
		if(s[0]=='0') //前置零 
		{
			cout<<"0\n";
			continue;
		}
		if(s[0]=='?')
		{
			ans*=10; pos=1;
		}
		for(int i=1;i<n;i++)
		{
			if(s[i]=='?') ans*=10;
		}
		if(pos==1) ans=ans/10*9;
		cout<<ans<<"\n";
	}
	return 0;
}

CF1821B Sort the Subarray

题意:给定数组a和a’,求最大的位置l,r,使得a[l]至a[r]以内的数排序后,a数组和a‘数组相同

思路:

1.队友思路:从左往右找不同,得l,从右往左找不同,得r,然后l向左扩展,r向右扩展(应该是非常正确的正解)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N=200000+100;
int n,a[N],b[N];
int l,r;
void work();

int main()
{
	int T; scanf("%d",&T);
	while(T--)
	{
		work();
	}
	return 0;
}
void work()
{
	scanf("%d",&n); l=-1;r=-1;
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);
	for(int i=1; i<=n; i++) scanf("%d",&b[i]);
	for(int i=1; i<=n; i++)
	{
		if(b[i]!=a[i])
		{
			l=i;
			break;
		}
	}
	for(int i=n; i>=1; i--)
	{
		if(b[i]!=a[i])
		{
			r=i;
			break;
		}
	}
	while(l>1)
	{
		if(b[l-1]<=b[l]) l--;
		else break;
	}
	while(r<n)
	{
		if(b[r+1]>=b[r]) r++;
		else break;
	}
	printf("%d %d\n",l,r);
}

2.我的思路:在左右找到不同之前,维护两个单调不减的子串(其实从本质上都是一样的)

#include<bits/stdc++.h>
using namespace std;
int t,n,minn,maxn,l,r,a[200010],b[200010];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		minn=100000000; maxn=0;
		l=0; r=100000000;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<=n;i++) cin>>b[i];
		for(int i=1;i<=n;i++)
		{
			if(a[i]==b[i])
			{
				if(a[i]<minn)
				{
					l=i; minn=a[i];
				}
				else minn=a[i];
			}
			else
			{
				if(i==1)
				{
					l=1; break;
				}
				if(b[i]<b[i-1]) l=i;
				break;
			}
		}
		for(int i=n;i>=1;i--)
		{
			if(a[i]==b[i])
			{
				if(a[i]>maxn)
				{
					r=i; maxn=a[i];
				}
				else maxn=a[i];
			}
			else
			{
				if(i==n)
				{
					r=i; break;
				}
				if(b[i]>b[i+1])	r=i; 
				break;
			}
		}
		cout<<l<<" "<<r<<"\n";
	}
	return 0;
}

注:其实这两种方法没有本质的区别,但是我想的时候没有深入(想到正解就开写了,没有去想怎么化简好一点),这样其实不太好,CF的比赛时间比较短,如果解法过于复杂会浪费蛮多时间。

CF1821C Tear It Apart

题意:给定一个字符串,可以进行若干次操作,每一次操作可以删掉若干个不相邻位置的字符,问最少需要多少次操作,可以使该串只剩一种字母。

思路:蛮简单的一个贪心,细细地试一下样例就可以明白,就是要找最小的同一字符间的最大间隔。

#include<bits/stdc++.h>
using namespace std;
int t,n,sum,pre,ans,sum2;
char s[200010];
int main()
{

	cin>>t;
	while(t--)
	{
		cin>>s; ans=0;
		n=strlen(s); sum=0; sum2=10000000000;
		for(int k=1;k<=26;k++)
		{
			sum=0;
			pre=0;
			for(int i=0;i<n;i++)
			{
				int now=s[i]-'a'+1;
				if(now==k)
				{
					if(pre==0)
					{
						pre=i+1;
						sum=max(sum,i);
					}
					else
					{
						sum=max(sum,i+1-pre-1);
						pre=i+1;
					}
				}
				if(i==n-1&&now!=k)
				{
					sum=max(sum,n-pre);
				}
			}
			
			sum2=min(sum2,sum);
		}
		while(sum2)
		{
			ans++;
			sum2/=2;
		}
		cout<<ans<<"\n";
	}
	return 0;
}

注:题目其实蛮简单,但是感觉自己代码实现得有点垃圾,还是感觉写复杂了,影响做题速度。

CF1821D Black Cells

思路:本质上来说,这也是一个贪心。首先,必然的是,一个区间的长度大于1时,那我们一定会把这个区间涂黑。对于长度为1的区间,如果最后一个区间还没涂完,我们一定会去涂最后一个区间而不涂长度为1的区间,如果最后一个区间也涂满了,还没有达到k,此时我们再考虑涂长度为1的区间。重要的是状态设定。我们遍历所有的区间,对于第i个区间,把它当成答案的最后一个区间,然后按照确定的优先级来选择区间(达到k就停止)1.选择1~i-1之间长度大于1的区间 2.选择涂第i个区间 3.选择涂i前面的长度为1的区间。

#define ll long long
#include<bits/stdc++.h>
using namespace std;
ll t,n,k,cnt,sum,ans=100000000000,l[300010],r[300010];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n>>k; cnt=0; ans=100000000000; sum=0; cnt=0;
		for(int i=1;i<=n;i++) cin>>l[i];
		for(int i=1;i<=n;i++) cin>>r[i];
		for(int i=1;i<=n;i++)
		{
			ll len=r[i]-l[i]+1;
			sum+=len;
			if(sum>=k&&sum-cnt-len<k)
			{
				if(sum-cnt>=k)//如果在最后一个区间里面选就可以大于K,就不用选长度为1的了 
				{
					ans=min(ans,(i-cnt)*2+l[i]+(k-(sum-len-cnt))-1);
				}
				else//选长度为1的 
				{
					ans=min(ans,(i-cnt)*2+r[i]+2*(k-(sum-cnt)));
				}
			}
			if(len==1)
			{
				cnt++;
			}
		}
		if(ans==100000000000) cout<<"-1\n";
		else cout<<ans<<"\n";
		
	}
	return 0;
}

注:其实今天上午思路出的还是比较快,调试的时候主要是表达式有些时候没注意写错了,下次应该先在纸上把每个表达式写好再打上去

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值