AtCoder Beginner Contest 337

传送门

A - Scoreboard

题意

给你n场比赛的结果

每一场比分 x:y 对应两个人的分数

要求输出n场总得分较高的队伍名称

若平局则输出“Draw”

思路

相加比较即可

code

#include<iostream>
#include<algorithm>
#include<map>
#include<cmath>
#include<set>
#include<vector>
#include<queue>
//#define int long long
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
const int M = 220;
int a[M];
int cnt1,cnt2;
void solve()
{
	int a,b; cin >> a >> b;
	cnt1 += a,cnt2 += b;
}

int main(){
	ios::sync_with_stdio(0); cin.tie(0),cout.tie(0);
	int t; cin >> t;
	int tt = t;
	while(t --) solve();
	if(cnt1 > cnt2) cout << "Takahashi";
	else if(cnt1 < cnt2) cout << "Aoki";
	else cout << "Draw";
	return 0;
}

B - Extended ABC

题意

给你一个字符串只包含ABC 要求出现的顺序严格满足 A ->  B -> C

在这个情况下可以满足输出Yes 否则No

思路

只要找到一个不满足的就行 也就是说

1. 在出现A之前不能出现B,C

2. 在出现B之前不能出现A

都满足就Yes

code

#include<iostream>
#include<algorithm>
#include<map>
#include<cmath>
#include<set>
#include<vector>
#include<queue>
//#define int long long
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
const int M = 220;
int cnt1,cnt2;
void solve()
{
	string a; cin >> a;
	int length = a.size();
	bool st1 = false,st2 = false,st3 = false;
	for(int i = 0;i < length;i ++)
	{
		if(a[i] == 'A') st1 = true;
		if(a[i] == 'B') st2 = true;
		if(a[i] == 'C') st3 = true;
		if(st2 || st3) 
		{
			if(a[i] == 'A') 
			{
				cout << "No\n";
				return;
			}
		}
		if(st3)
		{
			if(a[i] == 'B' || a[i] == 'A')
			{
				cout << "No\n";
				return;
			}
		}
	}
	cout << "Yes\n";
}

int main(){
	ios::sync_with_stdio(0); cin.tie(0),cout.tie(0);
	int t = 1;
	while(t --) solve();
	return 0;
}

C - Lining Up 2

题意

给你一个序列的长度N和序列A,表示一群人在排队买他们最爱的糯叽叽

规则如下:

1. 如果Ai = -1 表示 i 排在队列的最前面

2. 否则 i 紧跟在 Ai后面

现在要你还原真实队列顺序

思路

当时用的set容器想着这样找好快好省心

找到了存一个下标就行了

后来想想用链表就行了

code

#include<iostream>
#include<algorithm>
#include<map>
#include<cmath>
#include<set>
#include<vector>
#include<queue>
//#define int long long
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 3e5 + 10;
int a[N];
void solve()
{
	set<PII> se;
	int n; cin >> n;
	int shou = 0;
	for(int i = 1;i <= n;i ++)
	{
		int x; cin >> x;
		if(x == -1) shou = i;
		se.insert({x,i});
	}
	int idx = 1;
	a[idx++] = shou;
	PII now = {shou,0};
	while(idx <= n)
	{
		auto tmp = se.lower_bound(now);
		now = {tmp->second,0};	
		a[idx ++] = tmp -> second;
	}
	for(int i = 1;i <= n;i ++) cout << a[i] << ' ';
}  

int main(){
	ios::sync_with_stdio(0); cin.tie(0),cout.tie(0);
	int t = 1;
	while(t --) solve();
	return 0;
}

D - Cheating Gomoku Narabe

题意

给你一个字符矩阵的High,Width,一个长度K

表示你需要找到连续长K个字符,满足都是“。”(可以横着也可以竖着)

这个矩阵由('x','.','。')构成,像这样:

3 4 3
xo.x
..o.
xx.o

你有一个魔法可以让  '.'  变成 '。' 但是对于'x'无计可施

现在你要找到满足连续的长度为K的序列,期间所用魔法数最少的,输出这个次数

思路

滑动窗口

横着的全来一遍

竖着的全来一遍

以横着的全来一遍为例:

现在你在第一行遍历,首先把窗口固定在最开始的k列,统计'x'和‘。’的个数,在到达边界之前每次往右滑动窗口的时候都对个数进行更新,每次更新的同时更新minid也就是魔法施加的最小次数

code

现在说正事

老想着用queue但是发现根本不需要只要统计次数就行

两个版的代码都放一下,前后可以对照

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
const int INF = 0x3f3f3f3f;
void solve()
{
	int n,m,k; cin >> n >> m >> k;
//	char a[n+10][m+10];
	vector<vector<char>> a(n + 1, vector<char>(m + 1));
	for(int i = 1;i <= n;i ++)
		for(int j = 1;j <= m;j ++)
			cin >> a[i][j];
	// rows
	int minid = INF;
	if(k <= m)
	{
		for(int i = 1;i <= n;i ++)
		{
			int cnt = 0;
//			int cnt1 = 0;
			queue<int> q;
			for(int j = 1;j <= k;j ++)
			{
//				if(a[i][j] == 'x') cnt1 ++;
				if(a[i][j] == 'x') q.push(j);
				else if(a[i][j] == 'o') cnt ++;
			}
//			if(cnt1 == 0) minid = min(minid,k - cnt);
			if(q.empty()) minid = min(minid,k - cnt);
			for(int j = k + 1;j <= m;j ++)
			{
//				if(a[i][j] == 'x') cnt1 ++;
				if(a[i][j] == 'x') q.push(j);
				else if(a[i][j] == 'o') cnt ++;
//				if(a[i][j-k] == 'x') cnt1 --;
				if(a[i][j-k] == 'x') q.pop();
				else if(a[i][j-k] == 'o') cnt --;
//				if(cnt1 == 0) minid = min(minid,k-cnt);
				if(q.empty()) minid = min(minid,k - cnt);
			}
		}
	}
	// columns
	if(k <= n)
	{
		for(int j = 1;j <= m;j ++)
		{
			int cnt = 0;
//			int cnt1 = 0;
			queue<int> q;
			for(int i = 1;i <= k;i ++)
			{
//				if(a[i][j] == 'x') cnt1 ++;
				if(a[i][j] == 'x') q.push(j);
				else if(a[i][j] == 'o') cnt ++;
			}		
//			if(cnt1 == 0) minid = min(minid,k - cnt);
			if(q.empty()) minid = min(minid,k - cnt);
			for(int i = k + 1;i <= n;i ++)
			{
//				if(a[i][j] == 'x') cnt1 ++;
				if(a[i][j] == 'x') q.push(j);
				else if(a[i][j] == 'o') cnt ++;
//				if(a[i-k][j] == 'x') cnt1 --;
				if(a[i-k][j] == 'x') q.pop();
				else if(a[i-k][j] == 'o') cnt --;
//				if(cnt1 == 0) minid = min(minid,k-cnt);
				if(q.empty()) minid = min(minid,k - cnt);
			}
		}
	}
	if(minid < INF) cout << minid << '\n';
	else cout << "-1" << '\n';
}

int main()
{
	IOS;
	int tt; tt = 1;
	while(tt --) solve();
	return 0;
}

E - Bad Juice

题意

一道交互题

你有N瓶果汁 有一瓶变质了但你不知道是哪个 果汁有自己的标志 1,2,3,...,N。

你决定送给朋友一些瓶,你怎么给朋友都行,每个人收到的数量也不限。

Judge先生会告诉你送的那些朋友第二题喝完你送的果汁后有没有拉肚子。

用一个01串来表示 1代表拉肚子 也就是喝到了变质的饮料。

现在要你结合给你的N来决策:

你需要给几个朋友(你有无数个朋友)以及给他们哪几个果汁

还要结合Judge先生反馈的01串:

找到到底是哪瓶果汁变质了。

思路

假定给的N 转化为2进制后

你会发现N有几位你就需要给几个朋友

因为它的每一位都可以让一个朋友来承担

比如 N = 6 二进制表示成 110

那么果汁的下标是 001 010 011 100 101 110

那么你需要3个朋友

第一个朋友负责

第一个朋友负责第0位:3 bottles index=1,3,5

第二个朋友负责第1位:2 bottles index=2,6

第三个朋友负责第1位:2 bottles index=4,6

假如判官给的110那就证明 第二、三个朋友拉肚子 答案是6 也就是110

之所以这样是因为你的朋友就是代表了位数

特别的对于2次幂来说有一个最高位是不需要判断的 按上面的逻辑却被判断进去了

所以只需要在最开头统计位数的时候少统计一位

如果法官全给0 那就证明就是二次幂那个数 直接输出N即可

code

#include<iostream>
#include<cstdio>
#include<stack>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstring>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long long
//#define double long double
//#define PI acos(-1.0)
using namespace std;
typedef long long ll;
//const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
//typedef pair<char, int> PCI;

void solve()
{
	int n; cin >> n;
	int m = 0;
	while ((1ll << m) < n) m++;// 1算0位 4算2位 因为后面是从0开始算的
	cout << m << endl;
	for (int i = 0; i < m; i++)
	{
		vector<int> ve;
		for (int j = 1; j <= n; j++)
			if ((j >> i) & 1) ve.push_back(j);
		cout << ve.size() << ' ';
		for (auto it : ve) cout << it << ' ';
		cout << endl;
	}
	string st; cin >> st;
	int res = 0;
	for (int i = 0; i < m; i++)
	{
		if (st[i] == '1') res += (1ll << i);
	}
	if (res == 0) cout << n << endl;
	else cout << res << endl;
}

signed main()
{
	IOS;
	int tt = 1;
	while (tt--) solve();
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值