AtCoder Regular Contest 157——A-B题讲解

蒟蒻来讲题,还望大家喜。若哪有问题,大家尽可提!

Hello, 大家好哇!本初中生蒟蒻讲解一下AtCoder Regular Contest 157这场比赛的A-B题

===========================================================================================

A题——XXYYX

原题

Problem Statement

Determine whether there is a string S S S of length N N N consisting of X and Y that satisfies the following condition.
Condition: Among the ( N − 1 ) (N - 1) (N1) pairs of consecutive characters in S S S,
exactly A A A are XX,
exactly B B B are XY,
exactly C C C are YX, and
exactly D D D are YY.

Constraints

1 ≤ N ≤ 2 × 1 0 5 1 \leq N \leq 2 \times 10^5 1N2×105
A ≥ 0 A \geq 0 A0
B ≥ 0 B \geq 0 B0
C ≥ 0 C \geq 0 C0
D ≥ 0 D \geq 0 D0
A + B + C + D = N − 1 A + B + C + D = N - 1 A+B+C+D=N1

Input

The input is given from Standard Input in the following format:
N N N A A A B B B C C C D D D

Output

If there is a string S S S that satisfies the condition, print Yes; otherwise, print No.


Sample Input 1
5 1 1 1 1
Sample Output 1
Yes

For instance, if S = XXYYX, the pairs of consecutive characters are XX, XY, YY, and YX from left to right. Each pattern occurs exactly once, so the condition is satisfied.


Sample Input 2
5 1 2 1 0

Sample Output 2

Yes

For instance, S = XXYXY satisfies the condition.


Sample Input 3

5 0 4 0 0

Sample Output 3

No

No string satisfies the condition.

思路

我们通过成千上万次的找规律,会发现其实XXYY根本没有用,大家可以自行模拟~~~ 所以,有用的是XYYX,他们俩出现的次数之差必须小于等于1,否则会匹配不起来!当然又一个特殊的情况,如果XYYX出现的次数都是0,且XXYY都出现过,也是不行的,要输出NO,所以这里要特判一下~~~

代码

/*
------------------Welcome to Your Code--------------
Name:
Contest:AtCoder Regular Contest 157
Wishes:AK!
------------------Start Writing!!!------------------
*/
#include <iostream>
#define endl '\n'
#define pb(i) push_back(i)

using namespace std;

inline int read()
{
    int w = 1, s = 0;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') s = s * 10 + c - '0', c = getchar();
    
    return w * s;
}

int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    
    int n = read(), a = read(), b = read(), c = read() , d = read();
    
    if (abs(b - c) <= 1){ //注意要用绝对值
    	if(b == 0 and c == 0)//特判
    		if(a == n - 1 or d == n - 1)
    			cout << "Yes" <<endl;
    		else
    			cout << "No" <<endl;
    			
    	else cout << "Yes"<<endl;
    }
    else
    	cout << "No" <<endl;
 
    
    return 0;
}

B题——XYYYX

原题

Problem Statement

You are given a string S S S of length N N N consisting of X and Y.
You will choose K K K characters at distinct positions in S S S and change each of them: X becomes Y and Y becomes X.
Find the maximum possible number of pairs of consecutive Ys in the resulting string.

Constraints

1 ≤ N ≤ 2 × 1 0 5 1 \leq N \leq 2 \times 10^5 1N2×105
0 ≤ K ≤ N 0 \leq K \leq N 0KN
S S S is a string of length N N N consisting of X and Y.

Input

The input is given from Standard Input in the following format:
N N N K K K
S S S

Output

Print the maximum possible number of pairs of consecutive Ys in the resulting string.

Sample Input 1

5 1
XYXYX

Sample Output 1

2
You will choose one character.
If you choose the 1 1 1-st character, the resulting string is YYXYX, with one pair of consecutive Ys at positions 1 , 2 1, 2 1,2.
If you choose the 2 2 2-nd character, the resulting string is XXXYX, with no pair of consecutive Ys.
If you choose the 3 3 3-rd character, the resulting string is XYYYX, with two pairs of consecutive Ys at positions 2 , 3 2, 3 2,3 and 3 , 4 3, 4 3,4.
If you choose the 4 4 4-th character, the resulting string is XYXXX, with no pair of consecutive Ys.
If you choose the 5 5 5-th character, the resulting string is XYXYY, with one pair of consecutive Ys at positions 4 , 5 4, 5 4,5.
Thus, the sought maximum number is 2 2 2.

Sample Input 2

5 4
XYXYX

Sample Output 2

2
It is optimal to choose the 1 1 1-st, 2 2 2-nd, 3 3 3-rd, and 5 5 5-th characters to get YXYYY, or choose the 1 1 1-st, 3 3 3-rd, 4 4 4-th, and 5 5 5-th characters to get YYYXY.
Note that you may not choose a character at the same position multiple times.


思路

首先,通过直觉肯定是把X变成Y好!
我们可以发现有三种情况(设S中X的个数为cx)

  • c x = n cx = n cx=n ,则输出 m a x ( k − 1 , 0 ) max(k - 1, 0) max(k1,0)
  • k ≤ c x k \leq cx kcx,此时分为了三步
    • YXXX…XXXY中的所有X变成Y,此时会在原基础的YY个数上多一个!
    • Y旁边剩余不足 K K K个的X变成Y ,此时会多一个YY
    • 若S中有本来就有YY,那么加上原来就有的个数
  • k > c x k > cx k>cx,那么我们可以转换一下,其实就是把S中X变成YY变成X,然后此时是选 n − k n - k nkX,此时转换为了上文的 k ≤ c x k \leq cx kcx的情况

代码

/*
------------------Welcome to Your Code--------------
Name:
Contest:
Wishes:AK!
------------------Start Writing!!!------------------
*/
#include <iostream>
#define endl '\n'
#define pb(i) push_back(i)

using namespace std;

const int N = 2e5 + 10;

int n, k, res;
string s;
int pos[N], cnt;
int len[N];

inline int read()
{
    int w = 1, s = 0;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') s = s * 10 + c - '0', c = getchar();
    
    return w * s;
}

int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    
    cin >> n >> k >> s;
    
    int cx = 0;
    s = ' ' + s;
    for (int i = 1; i <= n; i ++) //记录Y的位置
    	if (s[i] == 'Y')
    		pos[++ cnt] = i;
    	else //记录X的个数
    		cx ++;
    			
    if (k > cx) //转换
    {
    	cx = cnt = 0;
    	for (int i = 1; i <= n; i ++)
    		s[i] = (s[i] == 'X') ? 'Y' : 'X';
    	for (int i = 1; i <= n; i ++)
    		if (s[i] == 'X')
    			cx ++;
    		else pos[++ cnt] = i;
    	k = n - k;
    }
    if (cx == n) //直接输出
    {
    	cout << max(k - 1, 0) << endl;
    	return 0;
    }
    
    for (int i = 1; i < cnt; i ++) //记录YXX...XXY情况中X..X的个数的序列所出现的次数
    	len[pos[i + 1] - pos[i] - 1] ++;
    
    for (int i = 1; i <= n && k; i ++) //通过贪心的思想,肯定是先找短的,这样多的那1个YY就能更快的得到
    	while (len[i] && k)
    		if (i <= k) //说明能把其中的X全变成Y
    			res += i + 1, k -= i, len[i] --;
    		else //只能变K个
    			res += k, k = 0;
    	
    if (k) res += k; //K还有剩余,全部变
    for (int i = 1; i < cnt; i ++) //若本来就有相邻的YY,记录上
		if (pos[i + 1] - pos[i] == 1)
			res ++;
			
	cout << res << endl; //输出结果
    
    return 0;
}

今天就到这里了!

大家有什么问题尽管提,我都会尽力回答的!

吾欲您伸手,点的小赞赞。吾欲您喜欢,点得小关注!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值