codeforces round 817 题解 A~F

A. Spell Check

A. Spell Check

题目大意

给定一个字符串并检测是否是原字符串的有效拼写。

思路

首先给定字符串长度要是五,然后统计出现的字符是不是都在原字符串中就可以了。具体看代码。

AC代码

#include<iostream>
#include<map>
using namespace std;

int main() {
	int t; cin >> t;
	while (t--) {
		int n; cin >> n;
		
		map<char, int> mp;
		string s; cin >> s;
		if (n > 5 || n < 5) {
			cout << "NO" << endl;
			continue;
		}
		for (int i = 0; i < s.length(); i++) {
			mp[s[i]]++;
		}
		int tmp = 0;
		for (auto it : mp) {
			if(it.second==1)
				if (it.first == 'T' || it.first == 'i' ||
					it.first == 'm' || it.first == 'u' ||
					it.first == 'r')
					tmp++;
		}
		if (tmp == 5)cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	return 0;
}

B. Colourblindness

B. Colourblindness

题目大意

有两行字符串,字符串中的字符代表颜色,这个人会将蓝色和绿色看成一个颜色,判断两个字符串是否在他眼里相同。

思路

就用字符1,2来表示每个字符,红色表示为1,蓝色和绿色表示为2,最后直接比较修改后的两个字符串是否相等就好了。

AC代码

#include<iostream>
using namespace std;
char tu[5][105];
int main() {
	int t; cin >> t;
	while (t--) {
		int n; cin >> n;
		for (int i = 1; i <= 2; i++) {
			for (int j = 1; j <= n; j++) {
				char ch; cin >> ch;
				if(ch=='R')
					tu[i][j] = '1';
				if (ch == 'G' || ch == 'B')
					tu[i][j] = '2';
			}
		}
		int f = 0;
		for (int i = 1; i <= n; i++) {
			if (tu[1][i] != tu[2][i]) {
				f = 1;
				break;
			}
		}
		if (f == 1)cout << "NO" << endl;
		else cout << "YES" << endl;
	}
}

C. Word Game

C. Word Game

题目大意

有三个人每个人写下n在这里插入图片描述
最终求每个人的得分

思路

枚举每个人,和当前的人所写的字符串,与其他两个人所写的字符串比较,并记录相同的个数。若当前人写的某个字符串,其余两个人都写了,那么当前人不得分,若当前人写的某个字符串,其余两人中一个人写了,那么当前人得1分。没人写得情况同理。

AC代码

#include<iostream>
#include<map>
using namespace std;
const int M = 1005;
string s[M][M];
int ans[5];
int main() {
	int t; cin >> t;
	while (t--) {
		map<string, int> mp[4];
		int n; cin >> n;
		for (int i = 1; i <= 3; i++) {
			ans[i] = 0;
			for (int j = 1; j <= n; j++) {
				cin >> s[i][j];
				mp[i][s[i][j]]++;
			}
		}
	/*	for (int i = 1; i <= 3; i++) {
			for (auto it : mp[i]) {
				cout << it.first << " ";
			}
			cout << endl;
		}*/
		for (int i = 1; i <= 3; i++) {
			int cnt = 0;
			for (int j = 1; j <= n; j++) {
				int tmp1 = (i + 1) % 3 == 0 ? 3 : (i + 1) % 3;
				int tmp2 = (i + 2) % 3 == 0 ? 3 : (i + 2) % 3;
				if (mp[tmp1].count(s[i][j]))
					cnt++;
				if (mp[tmp2].count(s[i][j]))
					cnt++;
				if (cnt == 0) ans[i] += 3;
				if (cnt == 1) ans[i] += 1;
				if (cnt == 2) ans[i] += 0;
				cnt = 0;
			}
			
		}
		for (int i = 1; i <= 3; i++) {
			cout << ans[i] << " ";
		}
		cout << endl;
	}
	return 0;
}

D. Line

D. Line

题目大意

在一条水平线上有 n个人,每个人要么向左看,要么向右看。每个人都数着他们所看方向的人数。这条线的是每个人计数的总和。最多可以改变1~n个人的看的方向,求每一个数量的改变后的值的最大值。

思路

求出每一个位置向左看或是向右看的价值,然后将这些价值升序排序,从n~1逐个选取求和就行了,当然要舍去负价值的可能改变。

AC代码

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int M = 2e5 + 5;
char zi[M];
ll val[M];
int main() {
	int t; cin >> t;
	while (t--) {
		int n; cin >> n;
		for (int i = 1; i <= n; i++) {
			cin >> zi[i];
			val[i] = 0;
		}
		ll ans = 0;
		for (int i = 1; i <= n; i++) {
			if (zi[i] == 'L') {
				ans += i - 1;	//原本的向左看的价值
				val[i] = n - 2 * i + 1; //向右看的价值与向左看的价值的差
			}
			else {
				ans += n - i;  //原本的向右看的价值
				val[i] = 2 * i - 1 - n; //向左看的价值与向右看的价值的差
			}
			
		}
		sort(val + 1, val + 1 + n);
		for (int i = n; i >= 1; i--) {
			if (val[i] > 0) ans += val[i];
			cout << ans << " ";
		}
		cout << endl;
	}
}

E. Counting Rectangles

E. Counting Rectangles

题目大意

给定数个矩形的长宽,然后给定q次查询,每次查询输入hs,ws,hb,wb代表在
在这里插入图片描述
在这里插入图片描述
长宽在这个区间范围内的矩形的面积总和。

思路

本题可以化为一个二维区间前缀和的问题。sum[i][j]就表示,长宽在i,j(包括i,j)之前的所有矩形的面积总和,这样的话求上面规定区间中的面积总和就好求了。
具体见代码

AC代码

#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int M = 1e3 + 5;
ll sum[M][M];
int main() {
	int t; cin >> t;
	while (t--) {
		int n, q; cin >> n >> q;
		memset(sum, 0, sizeof(sum));
		for (int i = 1; i <= n; i++) {
			ll h, w; cin >> h >> w;
			sum[h][w] += h * w;
		}
		for (int i = 1; i <= 1000; i++) {
			for (int j = 1; j <= 1000; j++) {
				sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
			}
		}
		for (int k = 1; k <= q; k++) {
			int hs, ws, hb, wb;
			cin >> hs >> ws >> hb >> wb;
			ll ans = sum[hb - 1][wb - 1] - sum[hb - 1][ws] - sum[hs][wb - 1] + sum[hs][ws];
			cout << ans << endl;
		}
	}
}

F. L-shapes

F. L-shapes

题目大意

一张网格纸,判断上面的阴影区域是否能且只能构成不相交,也不相接的L字形。

思路

两次广搜,第一次判断是否有且只有由三个连续的阴影块组成的阴影区域。
第二次判断阴影区域的形状是否都是L型。两条都满足,就YES,否则NO。

AC代码

#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
char mp[55][55];
int vis[55][55];
int mov[8][2] = { {-1,0},{1,0},{0,-1},{0,1} ,{1,1},{1,-1 },
{-1,1},{-1,-1} };
int n, m;
struct node {
	int x, y;
};
bool check(int x, int y) {
	return x >= 1 && x <= n && y >= 1 && y <= m;
}
vector<node> v;
void bfs(int x, int y) {
	queue<node> q;
	v.clear();
	q.push({ x,y });
	v.push_back({ x,y });
	vis[x][y] = 1;
	while (!q.empty()) {
		node now = q.front();
		q.pop();
		for (int i = 0; i <8; i++) {
			int xx = now.x + mov[i][0];
			int yy = now.y + mov[i][1];
			if (check(xx, yy) && !vis[xx][yy] && mp[xx][yy] == '*') {
				vis[xx][yy] = 1;
				v.push_back({ xx,yy });
				q.push({ xx,yy });
			}
		}
	}
}
char step[4] = { 'u','d','l','r' };
struct nodel {
	int x, y;
	string st;
	nodel(int a, int b, string c) {
		x = a; y = b; st = c;
	}
	nodel(){}
};
string bfs1(int x, int y) {
//	cout << x << " " << y << endl;
	string s = "";
	queue<nodel> q;
	q.push(nodel(x,y,s));
	vis[x][y] = 1;
	while (!q.empty()) {
		nodel p = q.front();
		q.pop();
		string tmp = p.st;
	//	cout << tmp << endl;
		if (tmp.size() == 2) return tmp;
		for (int i = 0; i < 4; i++) {
			int xx = p.x + mov[i][0];
			int yy = p.y + mov[i][1];
			if (check(xx, yy) && !vis[xx][yy] && mp[xx][yy] == '*') {
				vis[xx][yy] = 1;
				tmp += step[i];
		//		cout << tmp << endl;
				if (tmp.size() == 2) return tmp;
				q.push({ xx,yy ,tmp});
			}
		}
	}
	return "uu";
}
int main() {
	int t; cin >> t;
	while (t--) {
		cin >> n >> m;
		memset(mp, 0, sizeof(mp));
		memset (vis, 0, sizeof(vis));
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				cin >> mp[i][j];
			}
		}
		int f = 0;
		for (int i = 1; i <= n; i++) {
			for (int j =1 ; j <= m; j++) {
				if (!vis[i][j]&&mp[i][j]=='*') {
					bfs(i, j);
					if (v.size() != 3) {
						f = 1;
						break;
					}
				}
			}
			if (f == 1)break;
		}
		if (f == 1) cout << "NO" << endl;
		else {
			int che = 0;
			memset(vis, 0, sizeof(vis));
			for (int i = 1; i <= n; i++) {
				for (int j = 1; j <= m; j++) {
					if (mp[i][j] == '*' && !vis[i][j]) {
						string s=bfs1(i, j);
				//		cout << s << endl;
						if (s == "uu" || s == "ll" || s == "rr" ||
							s == "dd") {
							che = 1;
							break;
						}
					}
				}
				if (che == 1) break;
			}
			if (che == 1) cout << "NO" << endl;
			else
				cout << "YES" << endl;
		}
	}
}
  • 26
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值