Educational Codeforces Round 147 (Rated for Div. 2) A-D题解

发布时间 2023-04-23 17:50:46作者: HikariFears

A. Matching

题意:给出一个数,数中可能会有?,可以用0-9替换问号,问最后有多少种方法

Solution

对于位于首位的数可以用1-9替换,对于其他位置的额、可以用0-9替换,如果首位为0则无解

void solve()
{
	string s;cin>>s;
	if(s[0]=='0')
	{
		cout<<"0\n";
		return;
	}
	int ans=1;
	for(int i=0;i<s.length();i++)
	{
		if(s[i]=='?')
		{
			if(i==0)ans*=9;
			else ans*=10;
		}
	}
	cout<<ans<<"\n";
}

B. Sort the Subarray

题意:给两个数组,对于第一个数组可以选两个数l和r,将l和r按升序排序,要求排序后第一个数组与第二个数组相同,问使得结果成立的并且r-l最大的一对[l,r]

Solution

直接双指针遍历一遍找到需要排序的部分[l,r],然后向左遍历,如果a[l-1]<min[l,l+1,...r],那么可以把l-1加入,右边同理加入大于最大值的

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 l=1,r=n;
	int maxx=-1,minn=INF;
	while(l<r)
	{
		if(a[l]!=b[l]&&a[r]!=b[r])break;
		if(a[l]==b[l])l++;
		if(a[r]==b[r])r--;
	}
	for(int i=l;i<=r;i++)
	{
		maxx=max(maxx,a[i]);
		minn=min(minn,a[i]);
	}
	while(l>1)
	{
		if(a[l-1]<=minn)
		{
			l--;
			minn=a[l];
		}else break;
	}
	while(r<n)
	{
		if(a[r+1]>=maxx)
		{
			r++;
			maxx=a[r];
		}else break;
	}
	cout<<l<<" "<<r<<"\n";
}

C. Tear It Apart

题意:给一个由小写字母组成的字符串,每次可以选若干个不相邻的字符,将其删掉,使得最后的字符串只有一种字母,问最少的操作是多少次

Solution

枚举答案的字母char,将char之间的其他字母数量统计一下

我们可以发现,4要取3次,6要取3次,8要取4次,2要取2次

很显然答案就是
$$
log_2[MAX(len)]+1
$$

int dp[N];

void init()
{
	dp[0]=0;
	for(int i=1;i<N;i++)
	{
		int temp=i;
		int res=0;
		while(temp>0)
		{
			res++;
			temp/=2;
		}
		dp[i]=res;
	}
}

void solve()
{
	string s;cin>>s;
	int len=s.length();
	int ans=INF;
	for(int i=0;i<26;i++)
	{
		int res=0;
		int cnt=0;
		for(int j=0;j<=len;j++)
		{
			if(j==len||s[j]=='a'+i)
			{
				res=max(res,dp[cnt]);
				cnt=0;
			}
			else if(s[j]!='a'+i)cnt++;
			
		}
		//c//out<<(char)('a'+i)<<":"<<res<<"\n";
		ans=min(ans,res);
	}
	cout<<ans<<"\n";
}

D. Black Cells

题意:有一个长为1e18的,宽为1的方格,可以进行三种操作:

1.向右移动一格

2.按下按钮

3.松开按钮,将按下按钮到松开按钮的格子全部涂黑

给出n个区间,只能涂黑区间内的格子

问最小的操作次数使得k个格子被涂黑

Solution

长度大于等于2的区间必须涂黑,等于1的可以不涂黑,问我为什么?不知道,直觉

那么把记录一下长度为1的区间个数,最后与ans取一下小即可

void solve()
{
	int n,k;cin>>n>>k;
	for(int i=1;i<=n;i++)cin>>l[i];
	for(int i=1;i<=n;i++)cin>>r[i];
	int sum=0;
	for(int i=1;i<=n;i++)sum+=r[i]-l[i]+1;
	if(sum<k)  //判断有无解
	{
		cout<<"-1\n";
		return;
	}
	int cnt1=0;
	int cnt0=0;
	sum=0;
	int ans=1e18;
	for(int i=1;i<=n;i++)
	{
		sum+=r[i]-l[i]+1;
		int now=(r[i]-l[i]==0);
		cnt1+=now;
		cnt0+=now;
		if(sum>=k)
		{
			int maxx=sum-k;
			int len=r[i]-l[i]+1;
			int res=r[i]-maxx+min(maxx,cnt1)+2*(i-min(maxx,cnt1));
			
			
			
			
			ans=min(ans,res);
		}
		//cout<<cnt1<<"\n";
	}
	cout<<ans<<"\n";
	
}