Codeforces Round #817 (Div. 4)

A-Spell Check

         检查字符串是不是满足题目要求

        https://codeforces.com/contest/1722/problem/A

#include <bits/stdc++.h>
 
using namespace std ;
 
int main() {
	std::ios::sync_with_stdio(false) ;
	std::cin.tie(0) ;
	int T ;
	cin >> T ;
	while (T --) {
		int n ;
		cin >> n ;
		string s ;
		cin >> s ;
		map<char, int>mp ;
		if (n != 5)
			puts("NO") ;
		else {
			for (int i = 0 ; i < 5 ; i ++) {
				mp[s[i]] ++ ;
			}
			if (mp['T'] == 1 && mp['i'] == 1 && mp['m'] == 1
			        && mp['u'] == 1 && mp['r'] == 1)
				puts("YES") ;
			else
				puts("NO") ;
			mp.clear() ;
		}
	}
 
	return 0 ;
}
 

B-Colourblindness

        字符串,水

        https://codeforces.com/contest/1722/problem/B

#include <bits/stdc++.h>
 
using namespace std ;
 
int main() {
//	std::ios::sync_with_stdio
	int T ;
	cin >> T ;
	while (T --) {
		int n ;
		cin >> n ;
		string a, b ;
		cin >> a  ;
		cin >> b ;
 
//		cout << a << ' ' << b << '\n' ;
		string tmp1 = "", tmp2 = "" ;
		for (int i = 0 ; i < n ; i ++) {
			if (a[i] == 'G')
				tmp1 += 'B' ;
			else
				tmp1 += a[i] ;
		}
//		for(int i = 0 ; i )
		for (int i = 0 ; i < n ; i ++) {
			if (b[i] == 'G')
				tmp2 += 'B' ;
			else
				tmp2 += b[i] ;
		}
		if (tmp1 == tmp2)
			puts("YES") ;
		else
			puts("NO") ;
 
	}
	return 0 ;
}

C-Word Game

        map,水

        https://codeforces.com/contest/1722/problem/C

#include <bits/stdc++.h>
 
using namespace std ;
set<string>a, b, c ;
map<string, int> mp ;
int main() {
	std::ios::sync_with_stdio(false) ;
	std::cin.tie(0) ;
	int T ;
	cin >> T ;
	while (T --) {
		int n ;
		cin >> n ;
		a.clear(), b.clear(), c.clear() ;
		mp.clear() ;
		for (int i = 0 ; i < n ; i ++) {
			string x ;
			cin >> x ;
			a.insert(x) ;
			mp[x] ++ ;
		}
		for (int i = 0 ; i < n ; i ++) {
			string x ;
			cin >> x ;
			b.insert(x) ;
			mp[x] ++ ;
		}
		for (int i = 0 ; i < n ; i ++) {
			string x ;
			cin >> x ;
			c.insert(x) ;
			mp[x] ++ ;
		}
		int cnta = 0, cntb = 0, cntc = 0 ;
		for (auto i : mp) {
			if (i.second == 1) {
				string tmp = i.first ;
				if (a.count(tmp))
					cnta += 3 ;
				else if (b.count(tmp))
					cntb += 3 ;
				else
					cntc += 3 ;
			} else if (i.second == 2) {
				string tmp = i.first ;
				if (!a.count(tmp)) {
					cntb += 1, cntc += 1 ;
				} else if (!b.count(tmp)) {
					cnta += 1, cntc += 1 ;
				} else
					cnta += 1, cntb += 1 ;
			}
		}
		cout << cnta << ' ' << cntb << ' ' << cntc << '\n' ;
	}
	return 0 ;
}

D-Line

        https://codeforces.com/contest/1722/problem/D

        L表示向左看能看到的人数,R表示向右看能看到的人数,总价值等于所有人看到的人数。改变k次(k = 1 , 2 , ``` n ),每次可以把L变成R或者把R变成L,问每次改变后的最大值是多少。首先我们记录初始状态的总价值,然后对每个人把改变方向以后对于总价值的影响记录下来,从大到小排序,每次改变最大的就行

#include <bits/stdc++.h>
 
using namespace std ;
using ll = long long ;
 
int main() {
	std::ios::sync_with_stdio(false) ;
	std::cin.tie(0) ;
	int T ;
	cin >> T ;
	while (T --) {
		int n ;
		cin >> n ;
		string s ;
		cin >> s ;
		ll tot = 0 ;
		vector<ll> v ;
		for (int i = 0 ; i < n ; i ++) {
			if (s[i] == 'L') {
				v.push_back((n - i - 1) - i) ;        //记录改变方向对于总价值的影响
				tot += i ;
			} else {
				v.push_back(i - (n - i - 1)) ;
				tot += n - i - 1 ;
			}
		}
		sort(v.begin(), v.end(), greater<int>()) ;    //排序
		for (int i = 0 ; i < n ; i ++) {        //每次改变最大的
			if (v[i] > 0) {
				tot +=  v[i] ;
			}
			cout << tot << ' ' ;
		}
		cout << '\n' ;
//		puts("") ;
	}
 
	return 0 ;
}

E-Counting Rectangles

        https://codeforces.com/contest/1722/problem/E

        首先给你拥有的矩形块,然后每次询问给你另外两个矩形块S,B。要求你求出能够满足:你拥有的矩形块包含A,同时B包含你的拥有的矩形块的所有面积。

        可以通过二维前缀和来解决,把所有矩形都以(1,1)为起点,用pre[][]来代表(i , j)包含了从(1,1)到(i,j)的所有矩形块的面积值,同时题目还提到如果长宽都相等,不认为其具有包含或被包含关系

#include <bits/stdc++.h>
 
using namespace std ;
const int N = 1008 ;
using ll = long long ;
ll num[N][N] ;
ll pre[N][N] ;
 
 
int main() {
	std::ios::sync_with_stdio(false) ;
	std::cin.tie(0) ;
	int T ;
	cin >> T ;
	while (T --) {
		ll n, q ;
		cin >> n >> q ;
		for (int i = 0 ; i <= 1001 ; i ++) {
			for (int j = 0 ; j <= 1001 ; j ++) {
				num[i][j] = pre[i][j] = 0 ;            //初始化
			}
		}
 
		for (int i = 0 ; i < n ; i ++) {
			ll h, w ;
			cin >> h >> w ;
			num[h][w] += h * w ;        //num来记录面积价值
		}
 
		for (int i = 1 ; i <= 1000 ; i ++) {
			for (int j = 1 ; j <= 1000 ; j ++) {
				pre[i][j] = pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1] + num[i][j] ;           //构造前缀和
			}
		}
		while (q --) {
			ll hs, ws, hb, wb ;
			cin >> hs >> ws >> hb >> wb ;
			cout << pre[hb - 1][wb - 1] - pre[hb - 1][ws] - pre[hs][wb - 1] + pre[hs][ws] << '\n' ;        //因为题目的加粗条件,所以这里是[hb-1][wb-1]和[hs][ws] 
		}
	}
 
	return 0 ;
}

F-L-shapes

        https://codeforces.com/contest/1722/problem/F

        题目问是否有满足题意的“L”形块,要求不能相邻

        首先我们以"L"的拐点作为切入点,遍历图找*点,然后找它的水平和竖直方向是否也存在*点。如果存在且水平和竖直方向上的*点数量都是1,那么我们就认为它是一个“L”。相反,如果水平和竖直方向上的*点数量不等于1,那么我们可以直接输出“NO”。对于每一个已经找到的L,我们把L的三个点都给打上同一个标记。

        之后我们再一次遍历图,如果找到了*点,但是这个*点并没有被标记,我们也可以直接输出"NO"。然后对于每一个找到的*点,并且已经被标记了的,我们去找周围是不是有相邻的L,如果有直接输出"NO"。最后我们输出"YES"

#include <bits/stdc++.h>
 
using namespace std ;
using ll = long long ;
const int N = 1008 ;
 
const int dx[8] = {0, 0, 1, -1, 1, 1, -1, -1};
const int dy[8] = {1, -1, 0, 0, 1, -1, 1, -1} ;
 
void solve() {
	int n, m ;
	cin >> n >> m ;
	char g[n][m] ;
	int id[n][m] ;
	for (int i = 0 ; i < n ; i ++) {
		for (int j = 0 ; j < m ; j ++) {
			cin >> g[i][j] ;
			id[i][j] = 0 ;
		}
	}
	int curr = 1;        //标记
	for (int i = 0 ; i < n ; i ++) {
		for (int j = 0 ; j < m ; j ++) {
			if (g[i][j] == '*') {
				vector<pair<int, int>> adjh, adjv ;    //竖直和水平方向上是否存在*点
				if (i > 0 && g[i - 1][j] == '*') {
					adjh.emplace_back(i - 1, j) ;
				}
				if (i < n - 1 && g[i + 1][j] == '*') {
					adjh.emplace_back(i + 1, j) ;
				}
				if (j > 0 && g[i][j - 1] == '*') {
					adjv.emplace_back(i, j - 1) ;
				}
				if (j < m - 1 && g[i][j + 1] == '*') {
					adjv.emplace_back(i, j + 1) ;
				}
				if (adjh.size() == 1 && adjv.size() == 1) {   //如果都为1,就打上标记
					if (id[i][j] == 0)
						id[i][j] = curr ;
					else {
						cout << "NO" << '\n' ;
						return ;
					}
					if (id[adjh[0].first][adjh[0].second] == 0) {
						id[adjh[0].first][adjh[0].second] = curr ;
					} else {
						cout << "NO" << '\n' ;
						return ;
					}
					if (id[adjv[0].first][adjv[0].second] == 0) {
						id[adjv[0].first][adjv[0].second] = curr ;
					} else {
						cout << "NO" << '\n' ;
						return ;
					}
					curr ++ ;
				} else if (adjh.size() > 1 || adjv.size() > 1) {
					cout << "NO" << '\n' ;
					return ;
				}
			}
		}
	}
 
	auto judge = [&](int x, int y) {
		if (x >= 0 && x < n && y >= 0 && y < m)
			return true ;
		else
			return false ;
	} ;
 
	for (int i = 0 ; i < n ; i ++) {
		for (int j = 0 ; j < m ; j ++) {
			if (g[i][j] == '*') {
				if (id[i][j] == 0) {
					cout << "NO" << '\n' ;
					return ;
				} else {		//判断有没有相邻的
					for (int it = 0 ; it < 8 ; it ++) {
						int tx = i + dx[it] ;
						int ty = j + dy[it] ;
						if (judge(tx, ty) && id[tx][ty] != id[i][j] && id[tx][ty] != 0) {
							cout << "NO" << '\n' ;
							return ;
						}
					}
				}
			}
		}
	}
	cout << "YES" << '\n' ;
}
 
int main() {
	std::ios::sync_with_stdio(false) ;
	std::cin.tie(0) ;
	int T ;
	cin >> T ;
	while (T --) {
		solve() ;
	}
 
	return 0 ;
}

G-Even-Odd XOR

        https://codeforces.com/contest/1722/problem/G

        要求你给出n个不同的数组成的序列,里面的偶数下标异或起来等于奇数下标异或起来的值。通过观察我们可以发现,这n个数异或起来的值都是0.那么我们要组成一个n个数都异或起来等于0的值。同时有定理:设a为{1,...,n}的子集,b为a的补集,那么a中元素异或和等于b中元素异或和

 所以我们可以考虑先构造前n-2项

#include <bits/stdc++.h>
 
using namespace std ;
using ll = long long ;
const int N = 1008 ;
 
void solve() {
	int n ;
	cin >> n ;
	int case1 = 0, case2 = 0 ;
	for (int i = 0 ; i < n - 2 ; i ++) {
		case1 ^= i ;
		case2 ^= i + 1 ;
	}
	ll addlast = ((ll)1 << 31) - 1 ; //三十个1
	if (case1 != 0) {            
		for (int i = 0 ; i < n - 2 ; i ++) {
			cout << i << ' ' ;
		}
		case1 ^= addlast ;
		cout << addlast << ' ' << case1 << '\n' ;
	} else {
		for (int i = 1 ; i <= n - 2 ; i ++) {
			cout << i << ' ' ;
		}
		case2 ^= addlast ;
		cout << addlast << ' ' << case2 << '\n' ;
	}
}
 
int main() {
	std::ios::sync_with_stdio(false) ;
	std::cin.tie(0) ;
	int T ;
	cin >> T ;
	while (T --) {
		solve() ;
	}
 
	return 0 ;
}

水平有限 欢迎指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值