AtCoder Beginner Contest 337
ABC337总结
A - Scoreboard
翻译
Takahashi 队和 Aoki 队进行了\(N\)场比赛。在\(i\)/th比赛\((1\leq i\leq N)\)中,Takahashi 队得了\(X _ i\)分,Aoki 队得了\(Y _ i\)分。在\(N\)场比赛中总得分较高的队伍获胜。
输出获胜者。如果两队总得分相同,则输出 Draw
。
分析
将得分分别加起来进行比较即可。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,m,t,a[N];
int main ()
{
cin>>n;
for(int i=1;i<=n;i++)
{
int x,y;
cin>>x>>y;
m+=x,t+=y;
}
if(m>t) cout<<"Takahashi";
else if(m==t) cout<<"Draw";
else cout<<"Aoki";
return 0;
}
B - Extended ABC
翻译
我们将扩展 A 字符串、扩展 B 字符串、扩展 C 字符串和扩展 ABC 字符串定义如下:
- 如果 \(S\) 中的所有字符都是
A
,则字符串 \(S\) 是扩展A
字符串。 - 如果 \(S\) 中的所有字符都是
B
,则字符串 \(S\) 是扩展B
字符串。 - 如果 \(S\) 中的所有字符都是
C
,则字符串 \(S\) 是扩展C
字符串。 - 如果存在扩展 A 字符串 \(S_A\)、扩展 B 字符串 \(S_B\) 和扩展 C 字符串 \(S_C\),且按此顺序连接 \(S_A, S_B, S_C\) 得到的字符串等于 \(S\),则字符串 \(S\) 是扩展 ABC 字符串。
例如,ABC
、A
和AAABBBCCCCCCC
是扩展 ABC 字符串,但ABBAAAC
和BBBCCCCCCCAAA
不是。请注意,空字符串是扩展 A 字符串、扩展 B 字符串和扩展 C 字符串。
给您一个由 A
、B
和 C
组成的字符串 \(S\)。如果 \(S\) 是扩展 ABC 字符串,则输出 Yes
;否则输出 No
。
分析
设当前位置为 \(i\),按照题意,\(i+1\) 比 \(i\) 的字母的值大 \(1\) 或 \(0\),且只存在 A
B
C
。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,m,t,a[N];
int main ()
{
string s;
cin>>s;
int st=1;
for(char c:s)
{
if(c=='A'+t) continue;
if(c>'A'+t) t++;
if(c<'A'+t||t>2)
{
st=0;
break;
}
}
if(st) cout<<"Yes";
else cout<<"No";
return 0;
}
C - Lining Up 2
翻译
有\(N\)人在排队:\(1\)人、\(2\)人、\(\ldots\)人、\(N\)人。
给你的是长度为\(N\)的序列\(A=(A _ 1,A _ 2,\ldots,A _ N)\)。
\(A _ i\ (1\leq i\leq N)\) 表示以下信息:
- 如果是\(A _ i=-1\),则\(i\)排在队伍的最前面;
- 如果是\(A _ i\neq -1\),则\(i\)紧跟在\(A _ i\)后面。
从前面到后面输出一行人的编号。
分析
相当于告诉你每个人的前面是谁,直接用链表模拟即可。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int n,m,t,a[N],ne[N];
int main ()
{
cin>>n;
memset(ne,-1,sizeof(ne));
for(int i=1;i<=n;i++)
{
cin>>m;
if(m==-1) m=0;
ne[i]=ne[m];
ne[m]=i;
}
for(int i=ne[0];i;i=ne[i]) cout<<i<<" ";
return 0;
}
D - Cheating Gomoku Narabe
有一个网格,网格中有 \(H\) 行和 \(W\) 列。让 \((i, j)\) 表示从上往下第 \(i\) 行和从左往右第 \(j\) 列的单元格。
每个单元格包含一个字符 o
、x
和 .
。写在每个单元格中的字符由长度为\(W\)的\(H\)字符串\(S_1, S_2, \ldots, S_H\)表示;写在单元格\((i, j)\)中的字符是字符串\(S_i\)中的\(j\)个字符。
对于此网格,您可以重复以下操作任意多次,可能为零:
- 选择一个带有字符
.
的单元格,并将该单元格中的字符更改为o
。
确定是否有可能在所有单元格中都写上 o
的\(K\)个水平或垂直连续的单元格序列(换句话说,至少满足以下两个条件中的至少一个)。如果可能,请输出实现这一目标所需的最少操作数。
- 有一对整数\((i, j)\)满足\(1 \leq i \leq H\)和\(1 \leq j \leq W-K+1\),使得单元格\((i, j), (i, j+1), \ldots, (i, j+K-1)\)中的字符都是
o
。 - 有一个满足 \(1 \leq i \leq H-K+1\) 和 \(1 \leq j \leq W\) 的整数对 \((i, j)\) ,使得单元格 \((i, j), (i+1, j), \ldots, (i+K-1, j)\) 中的字符都是
o
。
分析
一开始想复杂了,其实暴力求就可以。每行每列分开看,用 \(cnt1\) 记录 o
的数量,用 \(cnt2\) 记录.
和 o
的数量,当 \(cnt2 \ge k\) 时,就计算答案。用类似滑动窗口,单调队列的思想,当 \(cnt2 > k\) 时,最开始的那个就对答案不产生影响,直接去掉,就是 cnt1--
。最后 \(ans=k-cnt1\),找出最小值。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m,k,ans=N;
string s[N];
int main ()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++) cin>>s[i],s[i]="0"+s[i];
for(int i=1;i<=n;i++)
{
int cnt1=0,cnt2=0;
for(int j=1;j<=m;j++)
{
if(s[i][j]=='x') cnt1=cnt2=0;
else if(s[i][j]=='o') cnt1++,cnt2++;
else cnt2++;
if(cnt2>k&&s[i][j-k]=='o') cnt1--;
if(cnt2>=k) ans=min(ans,k-cnt1);
}
}
for(int j=1;j<=m;j++)
{
int cnt1=0,cnt2=0;
for(int i=1;i<=n;i++)
{
if(s[i][j]=='x') cnt1=cnt2=0;
else if(s[i][j]=='o') cnt1++,cnt2++;
else cnt2++;
if(cnt2>k&&s[i-k][j]=='o') cnt1--;
if(cnt2>=k) ans=min(ans,k-cnt1);
}
}
if(ans==N) cout<<-1;
else cout<<ans;
return 0;
}
E - Bad Juice
翻译
有 \(n\) 杯果汁,其中一杯是发霉的,喝了发霉的果汁会窜稀。
现在你不知道哪杯是发霉的,但明天你要把这些果汁因此你想去坑你的好基友,让他们喝下这些果汁。每个基友可以喝很多杯果汁,每杯果汁可以被很多基友喝。
为了得罪尽量少的人,请求出最少需要给多少基友喝果汁,并构造出一种方案。
接下来用一个字符串 \(s\) 给出你的方案中每个人的窜稀情况,1
代表窜稀,0
代表没有窜稀。你需要据此输出发霉的果汁编号。
交互题。先读入 \(n\),然后输出方案,然后读入 \(s\),然后输出发霉的果汁编号。每次输出完需要刷新标准输出。编号全部从 \(1\) 开始。
交互方式示例:
请在输出完毕后使用 fflush(stdout)
或 endl
清空缓冲区,然后再获得下一个输入。
输入 | 输出 | 解释 |
---|---|---|
3 |
给出 \(n\)。 | |
2 |
输出叫的朋友人数。 | |
2 1 2 |
给第一个朋友喝果汁 \(1\) 和果汁 \(2\)。 | |
1 2 |
给第二个朋友喝果汁 \(2\)。 | |
10 |
给出每个朋友是否肚子疼。 | |
1 |
输出发霉的果汁编号。 |
分析
第一次做交互题,有点新奇但不多,就只需要读入输出再读入再输出就好了。本题方法略微有些新奇(幸好我见过 qwq),要运用二进制的方法,对于第 \(i\) 号朋友,需要给他喝所有编号二进制下从小到大第 \(i\) 位为 \(1\) 的果汁,这样如果他出事了,那么坏了的果汁在二进制下的第 \(i\) 位一定为 \(1\)(不为 \(1\) 就喝不到,也就不会出事)。那么 \(m=\log_2{n-1}+1\), 为何减一?如果 \(n\) 等于 \(2\) 的多少次方,那我就要让最后一位朋友和这第 \(n\) 号果汁,可我完全可以把第 \(n\) 号果汁留下,所有人都无事就能说明坏掉的果汁是第 \(n\) 号。
要注意交互题的一些注意事项。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,m,t,log_2[N];
string s;
int main ()
{
cin>>n;
for(int i=2;i<=n;i++) log_2[i]=log_2[i>>1]+1;
m=log_2[n-1]+1;
cout<<m<<"\n";
for(int i=0;i<m;i++)
{
int cnt=0;
for(int j=1;j<=n;j++) if((1<<i)&j) cnt++;
cout<<cnt<<" ";
for(int j=1;j<=n;j++) if((1<<i)&j) cout<<j<<" ";
cout<<"\n";
}
cin>>s;
int ans=0;
for(int i=0;i<s.size();i++) if(s[i]=='1') ans+=1<<i;
if(ans==0) ans=n;
cout<<ans;
return 0;
}