Codeforces Round #585 (Div. 2)(A,B,C,D,E)

比赛链接

A. Yellow Cards

题意:你有n张黄牌,有两只球队分别有a1,a2个人,两个球队的人分别吃k1,k2张黄牌就会被罚下场。问最多,最少可以使多少人被罚下场。

题解:贪心。让最多的人罚下场,先贪心选能吃黄牌少的人。让最少的人罚下场,就给每个人都分配k - 1张黄牌,多出的黄牌就是要罚出的人。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int a1, a2, k1, k2, n;
	scanf("%d%d%d%d%d", &a1, &a2, &k1, &k2, &n);
	int tmp1 = (k1 - 1) * a1 + (k2 - 1) * a2;
	int ans1 = 0, ans2 = 0;
	if(n > tmp1)
		ans1 = n - tmp1;
	if(k1 < k2){
		swap(k1,k2);
		swap(a1,a2);
	}
	if(n >= k2 * a2){
		n -= k2 * a2;
		ans2 += a2;
	}
	else {
		ans2 += n / k2;
		n = 0;
	}
	ans2 += n / k1;
	cout<<ans1<<' '<<ans2<<endl;
 } 

 

B. The Number of Products

题意:给你一个序列,问有多少个子区间乘积是正数,多少个是负数。

题解:简单区间问题一般涉及到前缀和知识。我们可以求一个前缀乘积,统计此时正数与负数的个数,然后开始遍历数组,遇到正数就正数的个数减1,遇到负数就负数的个数减1,然后因为少乘了一个负数,正负交换一下。实际就是遍历统计以当前位置为起始点到n的子区间的正负个数。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N];
int main()
{
	int n;
	cin>>n;
	int p1 = 0, p2 = 0, tmp = 1;
	for(int i = 1; i <= n; ++i){
		cin >> a[i];
		if(a[i] < 0) 
			a[i] = -1;
		else 
			a[i] = 1;
		tmp *= a[i];
		if(tmp > 0)
			p1++;
		else 
			p2++;
	}
	long long ans1 = 0, ans2 = 0, flg = 1;
	for(int i = 1; i <= n; ++i){
		ans1 += p1;
		ans2 += p2;
		if(a[i] == 1)
			p1 -= 1;
		else {
			p2 -= 1;
			swap(p1, p2);
		}
	} 
	cout << ans2 <<' '<<ans1<<endl;
}

 

C. Swap Letters

题意:有两个串 s ,t 只包含' a ' ,' b '字符,你可以交换 s 串和 t 串 任意位置的字符。问最少的交换次数,使s串与t串相等。

题解:首先可以发现两个串只有aa,ab,ba,bb四种情况,为了使s与t串相等,我们需要每次交换两个 ab 或者 ba,所以只能是偶数个ab,ba。统计ab与ba的个数,当(ba + ab)为奇数时无解。当ba 以及 ab 个数都为奇数个时,将一个 ba 变为 ab ,这样就都是偶数个了。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 100;
char s[N], t[N];
int vis[N];
struct node{
	int l, r;
}ans[N];
int main()
{
	int n;
	cin>>n;
	cin>>s + 1>>t + 1;
	int ab =0, ba = 0;
	for(int i = 1; i <= n; ++i){
		if(s[i] == 'a' && t[i] == 'b') ab++, vis[i] = 1;
		if(s[i] == 'b' && t[i] == 'a') ba++, vis[i] = 2;	
	}
	if((ab + ba) % 2 == 1) 
		return puts("-1");
	int cnt = 0;
	if(ab%2 == 1){
		for(int i = 1; i <= n; ++i){
			if(vis[i] == 1){
				vis[i] = 2;
				ans[++cnt] = node{i, i};
				break;
			}
		}
	}
	int pre = 0;
	for(int i = 1; i <= n; i++){
		if(vis[i] == 1){
			if(!pre)
				pre = i;
			else {
				ans[++cnt] = node{pre, i};
				pre = 0;
			}
		}
	}
	pre = 0;
	for(int i = 1; i <= n; i++){
		if(vis[i] == 2){
			if(!pre)
				pre = i;
			else {
				ans[++cnt] = node{pre, i};
				pre = 0;
			}
		}
	}
	cout<<cnt<<endl;
	for(int i = 1; i <= cnt; i++)
		printf("%d %d\n",ans[i].l, ans[i].r);
}

 

 

 D. Ticket Game

题意:给你一个串,包含0~9的数字以及?,?可以由两个玩家轮流填数,填数范围也是0~9。当序列中没有?时游戏结束,如果此时序列前半部分的和等于后半部分和,B赢否则M赢。

题解:统计前半部分以及后半部分和与?数量记为c1,c2,p1,p2,分四种情况:

  1. c1 == c2  p1 == p2 B赢,无论M怎么填数,B都可以在另一边填相同的数
  2. c1 != c2  p1 == p2  M赢,M在总和大的那一边一直填9就能赢了
  3. c1 == c2 p1 != p2 M赢,M在?多的那一边一直填9就赢了
  4. c1 != c2 p1 != p2 再分情况 , 假设c1 > c2
  5. 如果p1 > p2 M 赢 , 在前半部分 一直填 9 就好了
  6. 如果 p1 < p2 : p2 先 剪掉 p1 ,因为无论M怎么填,B都可以在另一边填相同的。然后再判断(c1 - c2)是否等于 p2 * 9
  7. 如果小于 ,M一直填0 ,M 赢。如果大于 M 一直填9,M赢。只有等于的时候,无论M怎么填,B都可以选出一个数与M凑成9,B赢。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
char s[N];
int main()
{
	int n;
	cin>>n;
	cin>>s + 1;
	int c1 = 0, c2 = 0, p1 = 0, p2 = 0;
	for(int i = 1; i <= n; ++i){
		if(i <= n / 2){
			if(s[i] == '?') p1++;
			if(s[i] >= '0' && s[i] <= '9')
				c1 += s[i] - '0';
		}
		else {
			if(s[i] == '?') p2++;
			if(s[i] >= '0' && s[i] <= '9')
				c2 += s[i] - '0';
		}
	}
	if(c1 == c2 && p1 == p2) puts("Bicarp");
	else if(c1 != c2 && p1 == p2) puts("Monocarp");
	else if(c1 == c2 && p1 != p2) puts("Monocarp");
	else {
		if(c1 < c2) {
			swap(c1, c2);
			swap(p1, p2);
		}
		if(p1 > p2) puts("Monocarp");
		else {
			p2 -= p1;
			if((p2 / 2) * 9 > c1 - c2 || (p2 / 2) * 9 < c1 -c2) puts("Monocarp");
			else puts("Bicarp");
		}
	}
}

E题加强了数据,一般做法是错的,一些AC代码过不了加强的数据,贴一下错误代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[25][25], cnt[2], ans;
int main()
{
	int n, x;
	cin>>n;
	for(int i = 1; i <= n; ++i){
		cin>>x;
		cnt[x]++;
		for(int j = 1; j <= 20; ++j)
			if(j != x)
				dp[x][j] += cnt[j];
	}
	for(int i = 1; i <= 20; ++i)
	for(int j = 1; j <= 20; ++j)
	if(i != j )
		ans += min(dp[i][j], dp[j][i]);
	cout<<ans/2<<endl;
 } 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值