AtCoder Beginner Contest 299——A-E题讲解

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

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

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

A - Treasure Chest

原题

Problem Statement

You are given a string S S S of length N N N consisting of three kinds of characters: ., |, and .
S S S contains exactly two | and exactly one .
Determine whether the is between the two |, and if so, print in; otherwise, print out.
More formally, determine whether one of the characters before the is | and one of the characters after the * is |.

Constraints

3 ≤ N ≤ 100 3\leq N\leq 100 3N100
N N N is an integer.
S S S is a string of length N N N consisting of ., |, and .
S S S contains exactly two |.
S S S contains exactly one .

Input

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

Output

Print a single line containing in if the * is between the two |, and out otherwise.

Sample Input 1
10
.|..*...|.
Sample Output 1
in

Between the two |, we have |……|, which contains , so you should print in.

Sample Input 2
10
.|..|.*...
Sample Output 2
out

Between the two |, we have |…|, which does not contain *, so you should print out.

Sample Input 3
3
|*|
Sample Output 3
in

题目大意

给定一个字符串 S S S,如果*在两个|之间,输出in,反之输出out


思路

可以依次枚举,枚举的同时记录出现|的次数,当出现*时,若|出现的次数为1,则输出in,反之输出out


代码

#include 
#include 
#include 
#define endl '\n'
#define psb(i) push_back(i)
#define ppb() pop_back()
#define psf(i) push_front(i)
#define ppf() pop_front()
#define ps(i) push(i)

using namespace std;

typedef pair<int, int> PII;

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;
    string s;
	
	cin >> n >> s;
	
	int shu = 0;
	for (auto c : s)
		if (c == '|') shu ++; //记录|出现的次数
		else if (c == '*') //出现了*
		{
			if (shu == 1) cout << "in" << endl; //说明在两个|之间
			else cout <<"out" << endl; //反之,就是外面
			return 0;
		}
    
    return 0;
}

B - Trick Taking

原题

Problem Statement

N N N players with ID numbers 1 , 2 , … , N 1, 2, \ldots, N 1,2,,N are playing a card game.

Each player plays one card.
Each card has two parameters: color and rank, both of which are represented by positive integers.

For i = 1 , 2 , … , N i = 1, 2, \ldots, N i=1,2,,N, the card played by player i i i has a color C i C_i Ci and a rank R i R_i Ri.
All of R 1 , R 2 , … , R N R_1, R_2, \ldots, R_N R1,R2,,RN are different.
Among the N N N players, one winner is decided as follows.

  • If one or more cards with the color T T T are played, the player who has played the card with the greatest rank among those cards is the winner.
  • If no card with the color T T T is played, the player who has played the card with the greatest rank among the cards with the color of the card played by player 1 1 1 is the winner. (Note that player 1 1 1 may win.)

Print the ID number of the winner.

Constraints

2 ≤ N ≤ 2 × 1 0 5 2 \leq N \leq 2 \times 10^5 2N2×105
1 ≤ T ≤ 1 0 9 1 \leq T \leq 10^9 1T109
1 ≤ C i ≤ 1 0 9 1 \leq C_i \leq 10^9 1Ci109
1 ≤ R i ≤ 1 0 9 1 \leq R_i \leq 10^9 1Ri109
i ≠ j    ⟹    R i ≠ R j i \neq j \implies R_i \neq R_j i=jRi=Rj
All values in the input are integers.

Input

The input is given from Standard Input in the following format:
N N N T T T
C 1 C_1 C1 C 2 C_2 C2 … \ldots C N C_N CN
R 1 R_1 R1 R 2 R_2 R2 … \ldots R N R_N RN

Output

Print the answer.

Sample Input 1

4 2
1 2 1 2
6 3 4 5

Sample Output 1

4
Cards with the color 2 2 2 are played.
Thus, the winner is player 4 4 4, who has played the card with the greatest rank, 5 5 5, among those cards.

Sample Input 2

4 2
1 3 1 4
6 3 4 5

Sample Output 2
1

No card with the color 2 2 2 is played.
Thus, the winner is player 1 1 1, who has played the card with the greatest rank, 6 6 6, among the cards with the color of the card played by player 1 1 1 (color 1 1 1).

Sample Input 3
2 1000000000
1000000000 1
1 1000000000
Sample Output 3
1

题目大意

N N N玩家中,一个赢家的决定如下。

  • 如果打出一张或多张颜色为 T T T的牌,那么在这些牌中打出排名最高的牌的玩家就是赢家。

  • 如果没有打出颜色为 T T T的牌,则在玩家 1 1 1所打出的牌的颜色中打出排名最大的牌的玩家为赢家。(注意,玩家 1 1 1可能会赢。)

输出赢家的编号


思路

这道题我们按照题目要求做就行,可以定义一个vector>(注:第一个参数表示排名,第二个参数表示人的编号,不能调换顺序,后面会讲why),把打出为T的牌的人的编号都放在里面。若该vector在放之后为空,则在把打出玩家1的牌的颜色的人的编号放入其中(玩家1也要放入)。
之后,按照题目要求我们要对第一个参数从大到小排序,而 s o r t sort sort自动是按第一个参数来排序,所以参数的位置不能调换!因为 s o r t sort sort是从小到大,再 r e v e r s e reverse reverse一下就行!


代码

#include 
#include 
#include 
#include 
#define endl '\n'
#define psb(i) push_back(i)
#define ppb() pop_back()
#define psf(i) push_front(i)
#define ppf() pop_front()
#define ps(i) push(i)

using namespace std;

typedef pair<int, int> PII;

const int  N = 2e5 + 10;

int n, t;
int c[N], r[N];
vector<PII> color;

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 >> t;
    
    for (int i = 1; i <= n; i ++)
    	cin >> c[i];
    for (int i = 1; i <= n; i ++)
    	cin >> r[i];
    	
    for (int i = 1; i <= n; i ++)
    	if (c[i] == t)
    		color.push_back({r[i], i});
    
    if (!color.size())
    	for (int i = 1; i <= n; i ++)
    		if (c[i] == c[1])
    			color.push_back({r[i], i});
	
	sort(color.begin(), color.end());
	reverse(color.begin(), color.end());
	
	cout << color[0].second << endl;
	
    return 0;
}

C - Dango

原题

Problem Statement

For a positive integer L L L, a level- L L L dango string is a string that satisfies the following conditions.

  • It is a string of length L + 1 L+1 L+1 consisting of o and -.
  • Exactly one of the first character and the last character is -, and the other L L L characters are o.

For instance, ooo- is a level- 3 3 3 dango string, but none of -ooo-, oo, and o-oo- is a dango string (more precisely, none of them is a level- L L L dango string for any positive integer L L L).
You are given a string S S S of length N N N consisting of the two characters o and -.
Find the greatest positive integer X X X that satisfies the following condition.

  • There is a contiguous substring of S S S that is a level- X X X dango string.
    If there is no such integer, print -1.
Constraints

1 ≤ N ≤ 2 × 1 0 5 1\leq N\leq 2\times10^5 1N2×105
S S S is a string of length N N N consisting of o and -.

Input

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

N
S
Output

Print the greatest positive integer X X X such that S S S contains a level- X X X dango string, or -1 if there is no such integer.

Sample Input 1
10
o-oooo---o
Sample Output 1
4

For instance, the substring oooo- corresponding to the 3 3 3-rd through 7 7 7-th characters of S S S is a level- 4 4 4 dango string.
No substring of S S S is a level- 5 5 5 dango string or above, so you should print 4 4 4.

Sample Input 2
1
-
Sample Output 2
-1

Only the empty string and - are the substrings of S S S.
They are not dango strings, so you should print -1.

Sample Input 3
30
-o-o-oooo-oo-o-ooooooo--oooo-o
Sample Output 3
7

题目大意

给出一个长度为 N N N的字符串 S S S,找到一个最长的dango,输出他的长度。
dango的定义如下:

  • 字符串长度为 L + 1 L+1 L+1,由0-组成。
  • 第一个字符和最后一个字符恰好是-,其他 L L L字符是o

思路

这道题通过观察,分两种情况:
情况1:
当没有0或没有-的时候,输出-1
情况2
最长dango的长度其实就是序列中最长连续o的个数。


代码

#include 
#include 
#include 
#define endl '\n'
#define psb(i) push_back(i)
#define ppb() pop_back()
#define psf(i) push_front(i)
#define ppf() pop_front()
#define ps(i) push(i)

using namespace std;

typedef pair<int, int> PII;

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;
    string s;
    
    cin >> n >> s;
    
    int len = 0, mx = 0, has1 = 0, has2 = 0;
    for (auto c : s)
    	if (c != 'o')
    		len = 0, has1 = 1;
    	else len ++, mx = max(mx, len), has2 = 1;
    
    if (!has1 || !has2)
    	cout << -1;
    else
    	cout << mx << endl;
    
    return 0;
}

D - Find by Query

原题

Problem Statement

This is an interactive task, where your program and the judge interact via Standard Input and Output.
The judge has a string of length N N N consisting of 0 0 0 and 1 1 1: S = S 1 S 2 … S N S = S_1S_2\ldots S_N S=S1S2SN.
Here, S 1 = 0 S_1 = 0 S1=0 and S N = 1 S_N = 1 SN=1.
You are given the length N N N of S S S, but not the contents of S S S.
Instead, you can ask the judge at most 20 20 20 questions as follows.
Choose an integer i i i such that 1 ≤ i ≤ N 1 \leq i \leq N 1iN and ask the value of S i S_i Si.
Print an integer p p p such that 1 ≤ p ≤ N − 1 1 \leq p \leq N-1 1pN1 and S p ≠ S p + 1 S_p \neq S_{p+1} Sp=Sp+1.

It can be shown that such p p p always exists under the settings of this problem.

Constraints

2 ≤ N ≤ 2 × 1 0 5 2 \leq N \leq 2 \times 10^5 2N2×105

Input and Output

First, receive the length N N N of the string S S S from Standard Input:

N

Then, you get to ask the judge at most 20 20 20 questions as described in the problem statement.
Print each question to Standard Output in the following format, where i i i is an integer satisfying 1 ≤ i ≤ N 1 \leq i \leq N 1iN:

? i

In response to this, the value of S i S_i Si will be given from Standard Input in the following format:

Si

Here, S i S_i Si is 0 0 0 or 1 1 1.
When you find an integer p p p satisfying the condition in the problem statement, print it in the following format, and immediately quit the program:

! $p$

If multiple solutions exist, you may print any of them.

Notes

Print a newline and flush Standard Output at the end of each message. Otherwise, you may get a TLE verdict.
If there is malformed output during the interaction or your program quits prematurely, the verdict will be indeterminate.
After printing the answer, immediately quit the program. Otherwise, the verdict will be indeterminate.
The string S S S will be fixed at the start of the interaction and will not be changed according to your questions or other factors.

Sample Input and Output

In the following interaction, N = 7 N = 7 N=7 and S = 0010011 S = 0010011 S=0010011.

Input Output Description
7 N is given.
? 1 Ask the value of S1.
0 The judge responds with S1 = 0.
? 6 Ask the value of S6.
1 The judge responds with S_6 = 1.
? 5 Ask the value of S_5.
0 The judge responds with S5 = 0.
! 5 Present p = 5 as an integer satisfying the condition.

For the presented p = 5 p = 5 p=5, we have 1 ≤ p ≤ N − 1 1 \leq p \leq N-1 1pN1 and S p ≠ S p + 1 S_p \neq S_{p+1} Sp=Sp+1.
Thus, if the program immediately quits here, this case will be judged as correctly solved.


题目大意

给出一个字符串的长度 N N N,字符串有01构成。

但字符串的内容是不知道的,唯一知道的是第一个字符是0且最后一个字符是1

当然,你可询问最多20次,每一次询问:

  • i i i个字符的值

思路

这道题是一道罕见的交互题,注意询问的格式和输出的格式,格式不当可能会TLE

这道题 2 × 1 0 5 2\times10^5 2×105的长度,却只能询问20次,又是在D题,那么我们想一想,使劲的想一想!

肯定是用二分啦!

二分的话,一log,我们询问的次数最多就只有18了!

然后,我们看一下怎么用二分~~~

关键因素:第一个字符是0且最后一个字符是1

这不仅是本题有解的条件,而且是我们能二分的必要条件。

这样来看,因为我们只用找一个,所以我们可以把除了那两个不同的左右两边分别看成01

就是这个样子: 00 … 0011 … 11 00\dots0011\dots11 00001111

然后我们只需找到第一个1左边的那个0的下标。
这就可以二分,若分到0就往右找,如果分到1就往左找。

最后,l的值就是答案!


代码

#include 
#include 

using namespace std;

int n;

int main()
{
	cin >> n;
	
	int l = 1, r = n;
	while (l <= r)
	{
		int mid = l + r >> 1;
		cout << "? " << mid << endl;
		int val;
		cin >> val;
		
		if (!val) l = mid + 1;
		else r = mid - 1;
	}
	
	cout << "! " << l - 1 << endl;
}

E - Nearest Black Vertex

原题

Problem Statement

You are given a simple connected undirected graph with N N N vertices and M M M edges (a simple graph contains no self-loop and no multi-edges).

For i = 1 , 2 , … , M i = 1, 2, \ldots, M i=1,2,,M, the i i i-th edge connects vertex u i u_i ui and vertex v i v_i vi bidirectionally.
Determine whether there is a way to paint each vertex black or white to satisfy both of the following conditions, and show one such way if it exists.
At least one vertex is painted black.
For every i = 1 , 2 , … , K i = 1, 2, \ldots, K i=1,2,,K, the following holds:
the minimum distance between vertex p i p_i pi and a vertex painted black is exactly d i d_i di.
Here, the distance between vertex u u u and vertex v v v is the minimum number of edges in a path connecting u u u and v v v.

Constraints

1 ≤ N ≤ 2000 1 \leq N \leq 2000 1N2000
N − 1 ≤ M ≤ min ⁡ { N ( N − 1 ) / 2 , 2000 } N-1 \leq M \leq \min\lbrace N(N-1)/2, 2000 \rbrace N1Mmin{N(N1)/2,2000}
1 ≤ u i , v i ≤ N 1 \leq u_i, v_i \leq N 1ui,viN
0 ≤ K ≤ N 0 \leq K \leq N 0KN
1 ≤ p 1 < p 2 < ⋯ < p K ≤ N 1 \leq p_1 \lt p_2 \lt \cdots \lt p_K \leq N 1p1<p2<<pKN
0 ≤ d i ≤ N 0 \leq d_i \leq N 0diN
The given graph is simple and connected.
All values in the input are integers.

Input

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

N N N M M M
u 1 u_1 u1 v 1 v_1 v1
u 2 u_2 u2 v 2 v_2 v2
⋮ \vdots
u M u_M uM v M v_M vM
K K K
p 1 p_1 p1 d 1 d_1 d1
p 2 p_2 p2 d 2 d_2 d2
⋮ \vdots
p K p_K pK d K d_K dK

Output

If there is no way to paint each vertex black or white to satisfy the conditions, print No.
Otherwise, print Yes in the first line, and a string S S S representing a coloring of the vertices in the second line, as shown below.
Here, S S S is a string of length N N N such that, for each i = 1 , 2 , … , N i = 1, 2, \ldots, N i=1,2,,N, the i i i-th character of S S S is 1 1 1 if vertex i i i is painted black and 0 0 0 if white.

Yes
S S S

If multiple solutions exist, you may print any of them.

Sample Input 1
5 5
1 2
2 3
3 1
3 4
4 5
2
1 0
5 2
Sample Output 1
Yes
10100

One way to satisfy the conditions is to paint vertices 1 , 3 1, 3 1,3 black and vertices 2 , 4 , 5 2, 4, 5 2,4,5 white.

Indeed, for each i = 1 , 2 , 3 , 4 , 5 i = 1, 2, 3, 4, 5 i=1,2,3,4,5, let A i A_i Ai denote the minimum distance between vertex i i i and a vertex painted black, and we have ( A 1 , A 2 , A 3 , A 4 , A 5 ) = ( 0 , 1 , 0 , 1 , 2 ) (A_1, A_2, A_3, A_4, A_5) = (0, 1, 0, 1, 2) (A1,A2,A3,A4,A5)=(0,1,0,1,2), where A 1 = 0 , A 5 = 2 A_1 = 0, A_5 = 2 A1=0,A5=2.

Sample Input 2
5 5
1 2
2 3
3 1
3 4
4 5
5
1 1
2 1
3 1
4 1
5 1
Sample Output 2
No

There is no way to satisfy the conditions by painting each vertex black or white, so you should print No.

Sample Input 3
1 0
0
Sample Output 3
Yes
1

题目大意

给出一个无向图(每条边的边权为1),请你给每个点染色(黑色或白色),使得:

  • 对与每一组 p i , d i p_i, d_i pi,di,离点 p i p_i pi最近的一个黑点的距离恰好是 d i d_i di

输出每个点最终的颜色,若没有合法的方案,输出No!


思路

对于这道题,我们首先想到的是进行BFS

所以,分为一下两个步骤:

步骤1:

进行一个BFS把经过的所有的在往外扩散 1 ∼ d i − 1 1\sim d_i-1 1di1层点(注:第 d i d_i di层的点染成黑色)染成白色,因为如果这些白色的点有一个或多个的点是黑色的,那么必定是不符合条件的,所以这些白色的点是固定的!

步骤2:

接下来,我们再染黑点,在染黑点的时候要注意,我们一定不能把白点染成黑点,如果最后没有然成功一个黑点,那么就要输出No了!

最后,我们把染好的点的颜色输出出来即可!

我做的比较麻烦,细节也比较多

注意:最开始要把颜色赋值为-1,若最后还有-1,按1输出即可

代码

本蒟蒻
#include 
#include 
#include 
#include 

using namespace std;

const int N = 2e4 + 10;
typedef pair<int, int> PII;

int n, m, k;
int u, v;
vector<int> g[N];
int p[N], d[N];
int color[N];
bool st[N];

void bfs(int u, int dis)
{
	queue<PII> q;
	
	q.push({1, u});
	if (dis) color[u] = 0;
	st[u] = 1;
	
	while (q.size() && q.front().first < dis)
	{
		auto t = q.front();
		q.pop();
		
		int deep = t.first, u = t.second;
		
		for (auto c : g[u])
			if (!st[c])
				st[c] = 1, color[c] = 0, q.push({deep + 1, c});
	}
}

void bfs2(int u, int dis)
{
	if (!dis)
		if (color[u] == 0)
		{
			cout << "No" << endl;
			exit(0);
		}
		else color[u] = 1;
	else
	{
		queue<PII> q;
	
		q.push({1, u});
		st[u] = 1;
		
		while (q.size() && q.front().first < dis)
		{
			auto t = q.front();
			q.pop();
			
			int deep = t.first, u = t.second;
			
			for (auto c : g[u])
				if (!st[c])
					st[c] = 1, q.push({deep + 1, c});
		}
		
		bool flg = 0;
		while (q.size())
		{
			auto t = q.front();
			q.pop();
			
			for (auto c : g[t.second])
			{
				if (color[c] == 0)
					continue;
				flg = 1;
				color[c] = 1;
			}
		}
			
		if (!flg)
		{
			cout << "No" << endl;
			exit(0);
		}
	}
}

int main()
{
	memset(color, -1, sizeof color);
	
	cin >> n >> m;
	
	for (int i = 1; i <= m; i ++)
		cin >> u >> v, g[u].push_back(v), g[v].push_back(u);
		
	cin >> k;
	
	for (int i = 1; i <= k; i ++)
	{
		cin >> p[i] >> d[i], bfs(p[i], d[i]);
		memset(st, 0, sizeof st);
	}
	for (int i = 1; i <= k; i ++)
	{
		bfs2(p[i], d[i]);
		memset(st, 0, sizeof st);
	}

	cout << "Yes" << endl;
	for (int i = 1; i <= n; i ++)
		if (color[i] == -1)
			cout << 1;
		else
			cout << color[i];
	
	return 0;
}

巨佬
#include 
#define int long long 
#define pb push_back
using namespace std;
const int INF=2e3+5;
int n,m,dis_[INF][INF],xx[INF],yy[INF],vis[INF];
vector <int> e[INF];
queue <int> q;
void BFS(int s) {
	memset(dis_[s],63,sizeof dis_[s]);
	q.push(s);dis_[s][s]=0;
	while (q.size()) {
		int x=q.front();q.pop();
		for (int v:e[x]) {
			if (dis_[s][v]>dis_[s][x]+1) {
				dis_[s][v]=dis_[s][x]+1;
				q.push(v); 
			}
		} 
	}
}
signed main()
{
	memset(vis,255,sizeof vis);
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for (int i=1;i<=m;i++) {
		int x=0,y=0;cin>>x>>y;
		e[x].pb(y);e[y].pb(x);
	}
	for (int i=1;i<=n;i++) BFS(i);
	int q=0;cin>>q;
	for (int i=1;i<=q;i++) {
		int x=0,y=0;cin>>x>>y;
		xx[i]=x;yy[i]=y;
		for (int j=1;j<=n;j++) {
			if (dis_[x][j]<y) {
				if (vis[j]==-1) vis[j]=0;
				else if (vis[j]) {cout<<"No\n";return 0;}
			}
		}
	}
	for (int i=1;i<=q;i++) {
		int x=xx[i],y=yy[i],fl=0;
		for (int j=1;j<=n;j++) {
			if (dis_[x][j]==y) {
				if (vis[j]==-1) fl=1;
			}
		}
		if (!fl) {cout<<"No\n";return 0;}
	}
	cout<<"Yes\n";
	for (int i=1;i<=n;i++)
		if (vis[i]==-1) cout<<"1";
		else cout<<"0";
	cout<<"\n";
	return 0;
}

今天就到这里了!

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

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

你可能感兴趣的:(算法-搜索,数学,算法-暴力,c++,算法,图论)